* [PATCH] IPv6 - support for NLM_F_* flags at IPv6 routing requests
From: Matti Vaittinen @ 2011-11-01 14:22 UTC (permalink / raw)
To: davem; +Cc: netdev
Hi dee Ho again.
Here's the support for NLM_F_* flags at IPv6 routing requests once again.
This time if no NLM_F_CREATE flag is not defined for RTM_NEWROUTE request,
warning is printed, but no error is returned. Instead new route is added.
Exception is when NLM_F_REPLACE flag is given without NLM_F_CREATE, and
no matching route is found. In this case it should be safe to assume
that the request issuer is familiar with NLM_F_* flags, and does really
not want route to be created.
Specifying NLM_F_REPLACE flag will now make the kernel to search for
matching route, and replace it with new one. If no route is found and
NLM_F_CREATE is specified as well, then new route is created.
Also, specifying NLM_F_EXCL will yield returning of error if matching route
is found.
Patch is created against linux-3.1-rc4
Best Regards
Matti Vaittinen
Signed-off-by: Matti Vaittinen <Mazziesaccount@gmail.com>
---
diff -uNr linux-3.1-rc4.orig/net/ipv6/ip6_fib.c linux-3.1-rc4.new/net/ipv6/ip6_fib.c
--- linux-3.1-rc4.orig/net/ipv6/ip6_fib.c 2011-11-01 14:01:55.000000000 +0200
+++ linux-3.1-rc4.new/net/ipv6/ip6_fib.c 2011-11-01 14:12:28.000000000 +0200
@@ -39,6 +39,7 @@
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
+#define RT6_CANT_CREATE ((int)-1)
#define RT6_DEBUG 2
#if RT6_DEBUG >= 3
@@ -429,17 +430,34 @@
static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
int addrlen, int plen,
- int offset)
+ int offset, struct nl_info *info)
{
struct fib6_node *fn, *in, *ln;
struct fib6_node *pn = NULL;
struct rt6key *key;
int bit;
+
+
+ int allow_create = 1;
+ int replace_required = 0;
+
+
__be32 dir = 0;
__u32 sernum = fib6_new_sernum();
RT6_TRACE("fib6_add_1\n");
+ if (NULL != info &&
+ NULL != info->nlh &&
+ (info->nlh->nlmsg_flags&NLM_F_REPLACE)) {
+ replace_required = 1;
+ }
+ if (NULL != info &&
+ NULL != info->nlh &&
+ !(info->nlh->nlmsg_flags&NLM_F_CREATE)) {
+ allow_create = 0;
+ }
+
/* insert node in tree */
fn = root;
@@ -451,8 +469,12 @@
* Prefix match
*/
if (plen < fn->fn_bit ||
- !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
+ !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit)) {
+ if (!allow_create)
+ printk(KERN_WARNING
+ "NLM_F_CREATE should be specified when creating new rt\n");
goto insert_above;
+ }
/*
* Exact match ?
@@ -481,10 +503,27 @@
fn = dir ? fn->right: fn->left;
} while (fn);
+
+ if (replace_required && !allow_create) {
+ /* We should not create new node because
+ * NLM_F_REPLACE was specified without NLM_F_CREATE
+ * I assume it is safe to require NLM_F_CREATE when
+ * REPLACE flag is used! Later we may want to remove the
+ * check for replace_required, because according
+ * to netlink specification, NLM_F_CREATE
+ * MUST be specified if new route is created.
+ * That would keep IPv6 consistent with IPv4
+ */
+ printk(KERN_WARNING
+ "NLM_F_CREATE should be specified when creating new rt - ignoring request\n");
+ return (struct fib6_node *)RT6_CANT_CREATE;
+ }
/*
* We walked to the bottom of tree.
* Create new leaf node without children.
*/
+ if (!allow_create)
+ printk(KERN_WARNING "NLM_F_CREATE should be specified when creating new rt\n");
ln = node_alloc();
@@ -567,7 +606,6 @@
fn->parent = in;
ln->fn_sernum = sernum;
-
if (addr_bit_set(addr, bit)) {
in->right = ln;
in->left = fn;
@@ -585,6 +623,7 @@
ln = node_alloc();
+
if (ln == NULL)
return NULL;
@@ -618,6 +657,12 @@
{
struct rt6_info *iter = NULL;
struct rt6_info **ins;
+ int replace = (NULL != info &&
+ NULL != info->nlh &&
+ (info->nlh->nlmsg_flags&NLM_F_REPLACE));
+ int add = ((NULL == info || NULL == info->nlh) ||
+ (info->nlh->nlmsg_flags&NLM_F_CREATE));
+ int found = 0;
ins = &fn->leaf;
@@ -630,6 +675,13 @@
/*
* Same priority level
*/
+ if (NULL != info->nlh &&
+ (info->nlh->nlmsg_flags&NLM_F_EXCL))
+ return -EEXIST;
+ if (replace) {
+ found++;
+ break;
+ }
if (iter->rt6i_dev == rt->rt6i_dev &&
iter->rt6i_idev == rt->rt6i_idev &&
@@ -659,19 +711,41 @@
/*
* insert node
*/
+ if (!replace) {
+ if (!add)
+ printk(KERN_WARNING "NLM_F_CREATE should be specified when creating new rt\n");
+
+add:
+ rt->dst.rt6_next = iter;
+ *ins = rt;
+ rt->rt6i_node = fn;
+ atomic_inc(&rt->rt6i_ref);
+ inet6_rt_notify(RTM_NEWROUTE, rt, info);
+ info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
+
+ if ((fn->fn_flags & RTN_RTINFO) == 0) {
+ info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
+ fn->fn_flags |= RTN_RTINFO;
+ }
- rt->dst.rt6_next = iter;
- *ins = rt;
- rt->rt6i_node = fn;
- atomic_inc(&rt->rt6i_ref);
- inet6_rt_notify(RTM_NEWROUTE, rt, info);
- info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
-
- if ((fn->fn_flags & RTN_RTINFO) == 0) {
- info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
- fn->fn_flags |= RTN_RTINFO;
+ } else {
+ if (!found) {
+ if (add)
+ goto add;
+ printk(KERN_WARNING "add rtinfo to node - NLM_F_REPLACE specified, but no existing node found! bailing out\n");
+ return -ENOENT;
+ }
+ *ins = rt;
+ rt->rt6i_node = fn;
+ rt->dst.rt6_next = iter->dst.rt6_next;
+ atomic_inc(&rt->rt6i_ref);
+ inet6_rt_notify(RTM_NEWROUTE, rt, info);
+ rt6_release(iter);
+ if ((fn->fn_flags & RTN_RTINFO) == 0) {
+ info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
+ fn->fn_flags |= RTN_RTINFO;
+ }
}
-
return 0;
}
@@ -700,10 +774,29 @@
{
struct fib6_node *fn, *pn = NULL;
int err = -ENOMEM;
+ int allow_create = 1;
+ int allow_replace = 1;
+ if (NULL != info &&
+ NULL != info->nlh &&
+ !(info->nlh->nlmsg_flags&NLM_F_REPLACE)) {
+ allow_replace = 0;
+ }
+ if (NULL != info &&
+ NULL != info->nlh &&
+ !(info->nlh->nlmsg_flags&NLM_F_CREATE)) {
+ allow_create = 0;
+ }
+ if (!allow_create && !allow_replace)
+ printk(KERN_WARNING "RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n");
fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
- rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst));
+ rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst),
+ info);
+ if (RT6_CANT_CREATE == (int)fn) {
+ err = -EINVAL;
+ fn = NULL;
+ }
if (fn == NULL)
goto out;
@@ -716,6 +809,8 @@
if (fn->subtree == NULL) {
struct fib6_node *sfn;
+ if (!allow_create)
+ printk(KERN_WARNING "NLM_F_CREATE should be specified when creating new rt\n");
/*
* Create subtree.
*
@@ -740,7 +835,8 @@
sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
sizeof(struct in6_addr), rt->rt6i_src.plen,
- offsetof(struct rt6_info, rt6i_src));
+ offsetof(struct rt6_info, rt6i_src),
+ info);
if (sn == NULL) {
/* If it is failed, discard just allocated
@@ -757,8 +853,13 @@
} else {
sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
sizeof(struct in6_addr), rt->rt6i_src.plen,
- offsetof(struct rt6_info, rt6i_src));
+ offsetof(struct rt6_info, rt6i_src),
+ info);
+ if (RT6_CANT_CREATE == (int)sn) {
+ err = -EINVAL;
+ sn = NULL;
+ }
if (sn == NULL)
goto st_failure;
}
diff -uNr linux-3.1-rc4.orig/net/ipv6/route.c linux-3.1-rc4.new/net/ipv6/route.c
--- linux-3.1-rc4.orig/net/ipv6/route.c 2011-11-01 14:01:55.000000000 +0200
+++ linux-3.1-rc4.new/net/ipv6/route.c 2011-10-27 10:45:05.000000000 +0300
@@ -1223,9 +1223,18 @@
if (cfg->fc_metric == 0)
cfg->fc_metric = IP6_RT_PRIO_USER;
- table = fib6_new_table(net, cfg->fc_table);
+ err = -ENOBUFS;
+ if (NULL != cfg->fc_nlinfo.nlh &&
+ !(cfg->fc_nlinfo.nlh->nlmsg_flags&NLM_F_CREATE)) {
+ table = fib6_get_table(net, cfg->fc_table);
+ if (table == NULL) {
+ printk(KERN_WARNING "NLM_F_CREATE should be specified when creating new rt\n");
+ table = fib6_new_table(net, cfg->fc_table);
+ }
+ } else {
+ table = fib6_new_table(net, cfg->fc_table);
+ }
if (table == NULL) {
- err = -ENOBUFS;
goto out;
}
^ permalink raw reply
* Re: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address filtering support for passthru mode
From: Roopa Prabhu @ 2011-11-01 12:17 UTC (permalink / raw)
To: Rose, Gregory V, netdev@vger.kernel.org
Cc: sri@us.ibm.com, dragos.tatulea@gmail.com, kvm@vger.kernel.org,
arnd@arndb.de, mst@redhat.com, davem@davemloft.net,
mchan@broadcom.com, dwang2@cisco.com, shemminger@vyatta.com,
eric.dumazet@gmail.com, kaber@trash.net, benve@cisco.com
In-Reply-To: <43F901BD926A4E43B106BF17856F075501A1BD52F6@orsmsx508.amr.corp.intel.com>
On 10/31/11 10:39 AM, "Rose, Gregory V" <gregory.v.rose@intel.com> wrote:
>> -----Original Message-----
>> From: Roopa Prabhu [mailto:roprabhu@cisco.com]
>> Sent: Monday, October 31, 2011 10:09 AM
>> To: Rose, Gregory V; netdev@vger.kernel.org
>> Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; kvm@vger.kernel.org;
>> arnd@arndb.de; mst@redhat.com; davem@davemloft.net; mchan@broadcom.com;
>> dwang2@cisco.com; shemminger@vyatta.com; eric.dumazet@gmail.com;
>> kaber@trash.net; benve@cisco.com
>> Subject: Re: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address
>> filtering support for passthru mode
>>
>>
>>
>>
>> On 10/31/11 9:38 AM, "Rose, Gregory V" <gregory.v.rose@intel.com> wrote:
>>
>>>> -----Original Message-----
>>>> From: netdev-owner@vger.kernel.org [mailto:netdev-
>> owner@vger.kernel.org]
>>>> On Behalf Of Roopa Prabhu
>>>> Sent: Friday, October 28, 2011 7:34 PM
>>>> To: netdev@vger.kernel.org
>>>> Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; kvm@vger.kernel.org;
>>>> arnd@arndb.de; mst@redhat.com; davem@davemloft.net; Rose, Gregory V;
>>>> mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
>>>> eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
>>>> Subject: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address filtering
>>>> support for passthru mode
>>>>
>>>> v2 -> v3
>>>> - Moved set and get filter ops from rtnl_link_ops to netdev_ops
>>>> - Support for SRIOV VFs.
>>>> [Note: The get filters msg might get too big for SRIOV vfs.
>>>> But this patch follows existing sriov vf get code and
>>>> accomodate filters for all VF's in a PF.
>>>> And for the SRIOV case I have only tested the fact that the VF
>>>> arguments are getting delivered to rtnetlink correctly. The rest of
>>>> the code follows existing sriov vf handling code so it should work
>>>> just fine]
>>>> - Fixed all op and netlink attribute names to start with IFLA_RX_FILTER
>>>> - Changed macvlan filter ops to call corresponding lowerdev op if
>> lowerdev
>>>> supports it for passthru mode. Else it falls back on macvlan handling
>>>> the
>>>> filters locally as in v1 and v2
>>>>
>>>> v1 -> v2
>>>> - Instead of TUNSETTXFILTER introduced rtnetlink interface for the same
>>>>
>>>
>>> [snip...]
>>>
>>>>
>>>> This patch series implements the following
>>>> 01/6 rtnetlink: Netlink interface for setting MAC and VLAN filters
>>>> 02/6 netdev: Add netdev_ops to set and get MAC/VLAN rx filters
>>>> 03/6 rtnetlink: Add support to set MAC/VLAN filters
>>>> 04/6 rtnetlink: Add support to get MAC/VLAN filters
>>>> 05/6 macvlan: Add support to set MAC/VLAN filter netdev ops
>>>> 06/6 macvlan: Add support to get MAC/VLAN filter netdev ops
>>>>
>>>> Please comment. Thanks.
>>>
>>> After some preliminary review this looks pretty good to me in so far as
>> adding
>>> the necessary hooks to do what I need to do. I appreciate your effort
>> on
>>> this.
>>>
>>> I'm sort of a hands-on type of person so I need to apply this patch to a
>>> private git tree and then take it for a test drive (so to speak). If I have
>>> further comments I'll get back to you.
>>>
>> Sounds good.
>>
>>> Did you have any plans for modifying any user space tools such as 'ip' to
>>> use
>>> this interface?
>>>
>>
>> Yes, I have an iproute2 sample patch for setting and displaying the filters
>> which I have been using to test this interface. I can send the patch to you
>> after some cleanup if you think it will be useful for you to try out this
>> interface.
>>
>> Thanks Greg.
>
> Yes, please do.
>
> Thanks,
>
> - Greg
>
Greg, here is the patch. I rebased it with tip-of-tree iproute2 git. Thanks.
iproute2: support for MAC/VLAN filter
This patch is not complete. Its a bit hackish right now.
I implemented this patch to only test the kernel interface
without usability in mind.
Limitations:
- Havent checked corner cases for sriov vfs
- usage msg needs to be fixed. Its ugly right now
- vf = -1 for direct assignment of filters on a vf or any network
interface
- functions could be broken down, var names changed etc
- show part definately needs to change. It does not
follow the convention right now
- it has some redundant code which can be removed and simplified
I will work on this patch some more and resubmit this patch
after the kernel patch gets accepted.
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 304c44f..ffd03e1 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -137,6 +137,8 @@ enum {
IFLA_AF_SPEC,
IFLA_GROUP, /* Group the device belongs to */
IFLA_NET_NS_FD,
+ IFLA_VF_RX_FILTERS,
+ IFLA_RX_FILTER,
__IFLA_MAX
};
@@ -264,6 +266,8 @@ enum macvlan_mode {
/* SR-IOV virtual function management section */
+#define SELF_VF -1
+
enum {
IFLA_VF_INFO_UNSPEC,
IFLA_VF_INFO,
@@ -378,4 +382,63 @@ struct ifla_port_vsi {
__u8 pad[3];
};
+/* VF rx filters management section
+ *
+ * Nested layout of set/get msg is:
+ *
+ * [IFLA_VF_RX_FILTERS]
+ * [IFLA_VF_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ * [IFLA_VF_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ * ...
+ * [IFLA_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ */
+enum {
+ IFLA_VF_RX_FILTER_UNSPEC,
+ IFLA_VF_RX_FILTER, /* nest */
+ __IFLA_VF_RX_FILTER_MAX,
+};
+
+#define IFLA_VF_RX_FILTER_MAX (__IFLA_VF_RX_FILTER_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_UNSPEC,
+ IFLA_RX_FILTER_VF, /* __u32 */
+ IFLA_RX_FILTER_ADDR,
+ IFLA_RX_FILTER_VLAN,
+ __IFLA_RX_FILTER_MAX,
+};
+#define IFLA_RX_FILTER_MAX (__IFLA_RX_FILTER_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_ADDR_UNSPEC,
+ IFLA_RX_FILTER_ADDR_FLAGS,
+ IFLA_RX_FILTER_ADDR_UC_LIST,
+ IFLA_RX_FILTER_ADDR_MC_LIST,
+ __IFLA_RX_FILTER_ADDR_MAX,
+};
+#define IFLA_RX_FILTER_ADDR_MAX (__IFLA_RX_FILTER_ADDR_MAX - 1)
+
+#define RX_FILTER_FLAGS (IFF_UP | IFF_BROADCAST | IFF_MULTICAST | \
+ IFF_PROMISC | IFF_ALLMULTI)
+
+enum {
+ IFLA_ADDR_LIST_UNSPEC,
+ IFLA_ADDR_LIST_ENTRY,
+ __IFLA_ADDR_LIST_MAX,
+};
+#define IFLA_ADDR_LIST_MAX (__IFLA_ADDR_LIST_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_VLAN_UNSPEC,
+ IFLA_RX_FILTER_VLAN_BITMAP,
+ __IFLA_RX_FILTER_VLAN_MAX,
+};
+#define IFLA_RX_FILTER_VLAN_MAX (__IFLA_RX_FILTER_VLAN_MAX - 1)
+
+#define VLAN_BITMAP_SPLIT_MAX 8
+#define VLAN_BITMAP_SIZE (VLAN_N_VID/VLAN_BITMAP_SPLIT_MAX)
+
#endif /* _LINUX_IF_LINK_H */
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 85f05a2..4154b07 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -192,6 +192,120 @@ static void print_linktype(FILE *fp, struct rtattr
*tb)
}
}
+static void print_vlan_bitmap(FILE *fp, struct rtattr *vlan_bitmap)
+{
+ unsigned long active_vlans[4096/64];
+ int i = 0, j = 0;
+ int first = 1;
+
+ memcpy(active_vlans, RTA_DATA(vlan_bitmap), sizeof(active_vlans));
+
+ for (i = 0 ; i < 64; i++) {
+ for (j = 0; j < 64; j++) {
+ if (((active_vlans[i] >> j) & 1UL) == 1 ) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+
+ fprintf(fp, "%d", j + 64 * i);
+ }
+ }
+ }
+}
+
+static void print_rx_filter(FILE *fp, struct rtattr *tb)
+{
+ struct rtattr *rx_filter[IFLA_RX_FILTER_MAX+1];
+ int first;
+
+ parse_rtattr_nested(rx_filter, IFLA_RX_FILTER_MAX, tb);
+
+ fprintf(fp, "rx_filter ");
+ if (rx_filter[IFLA_RX_FILTER_VF])
+ fprintf(fp, "vf:%d ",
+ *(unsigned int *)RTA_DATA(rx_filter[IFLA_RX_FILTER_VF]));
+
+ if (rx_filter[IFLA_RX_FILTER_ADDR]) {
+ struct rtattr *rx_addr_filter[IFLA_RX_FILTER_ADDR_MAX+1];
+ unsigned int flags;
+
+ parse_rtattr_nested(rx_addr_filter, IFLA_RX_FILTER_ADDR_MAX,
+ rx_filter[IFLA_RX_FILTER_ADDR]);
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_FLAGS]) {
+ flags = *(unsigned int *)RTA_DATA(
+ rx_addr_filter[IFLA_RX_FILTER_ADDR_FLAGS]);
+ fprintf(fp, "flags IFF_UP=%s, "
+ "IFF_BROADCAST=%s, "
+ "IFF_MULTICAST=%s, IFF_PROMISC=%s, "
+ "IFF_ALLMULTI=%s ",
+ ((flags & IFF_UP) ? "on" : "off"),
+ ((flags & IFF_BROADCAST) ? "on" : "off"),
+ ((flags & IFF_MULTICAST) ? "on" : "off"),
+ ((flags & IFF_PROMISC) ? "on" : "off"),
+ ((flags & IFF_ALLMULTI) ? "on" : "off"));
+ }
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_UC_LIST]) {
+ struct rtattr *i;
+ struct rtattr *uclist =
rx_addr_filter[IFLA_RX_FILTER_ADDR_UC_LIST];
+ int rem = RTA_PAYLOAD(uclist);
+ SPRINT_BUF(b1);
+ first = 1;
+ fprintf(fp, " uc ");
+ for (i = RTA_DATA(uclist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+ fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(i),
+ RTA_PAYLOAD(i), 0, b1, sizeof(b1)));
+ }
+ }
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_MC_LIST]) {
+ struct rtattr *i;
+ struct rtattr *mclist =
rx_addr_filter[IFLA_RX_FILTER_ADDR_MC_LIST];
+ SPRINT_BUF(b1);
+ int rem = RTA_PAYLOAD(mclist);
+
+ first = 1;
+ fprintf(fp, " mc ");
+ for (i = RTA_DATA(mclist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+ fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(i),
+ RTA_PAYLOAD(i), 0, b1, sizeof(b1)));
+ }
+ }
+ }
+
+ if (rx_filter[IFLA_RX_FILTER_VLAN]) {
+ struct rtattr *rx_vlan_filter[IFLA_RX_FILTER_VLAN_MAX+1];
+
+ fprintf(fp, " vlans ");
+ parse_rtattr_nested(rx_vlan_filter, IFLA_RX_FILTER_VLAN_MAX,
+ rx_filter[IFLA_RX_FILTER_VLAN]);
+ print_vlan_bitmap(fp,
+ rx_vlan_filter[IFLA_RX_FILTER_VLAN_BITMAP]);
+ }
+ fprintf(fp, "\n");
+}
+
+static void print_vf_rx_filters(FILE *fp, struct rtattr *tb)
+{
+ struct rtattr *i, *vf_filters = tb;
+ int rem = RTA_PAYLOAD(vf_filters);
+
+ for (i = RTA_DATA(vf_filters); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
+ print_rx_filter(fp, i);
+}
+
static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
{
struct ifla_vf_mac *vf_mac;
@@ -319,6 +433,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (do_link && tb[IFLA_LINKINFO] && show_details)
print_linktype(fp, tb[IFLA_LINKINFO]);
+ if (do_link && tb[IFLA_RX_FILTER] ) {
+ fprintf(fp, "\n\t");
+ print_rx_filter(fp, tb[IFLA_RX_FILTER]);
+ }
+
+ if (do_link && tb[IFLA_VF_RX_FILTERS] ) {
+ fprintf(fp, "\n\t");
+ print_vf_rx_filters(fp, tb[IFLA_VF_RX_FILTERS]);
+ }
+
if (do_link && tb[IFLA_IFALIAS])
fprintf(fp,"\n alias %s",
(const char *) RTA_DATA(tb[IFLA_IFALIAS]));
diff --git a/ip/iplink.c b/ip/iplink.c
index 35e6dc6..42897fb 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -71,7 +71,8 @@ void iplink_usage(void)
fprintf(stderr, " [ alias NAME ]\n");
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ]
]\n");
- fprintf(stderr, " [ rate TXRATE ] ] \n");
+ fprintf(stderr, " [ rate TXRATE ] \n");
+ fprintf(stderr, " [ rx_filter [flags
FILTER_FLAGS uc UC_LIST mc MC_LIST] [vlan VLANID_LIST]]\n");
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ]\n");
@@ -79,6 +80,10 @@ void iplink_usage(void)
if (iplink_have_newlink()) {
fprintf(stderr, "\n");
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb |
macvlan | can | bridge }\n");
+ fprintf(stderr, "FILTER_FLAGS := ifup,\n");
+ fprintf(stderr, "UC_LIST := <coma_separated_list_of_unicast
addrs>\n");
+ fprintf(stderr, "MC_LIST := <coma_separated_list_of_multicast
addrs>\n");
+ fprintf(stderr, "VLANID_LIST :=
<coma_separated_list_of_vlanids>\n");
}
exit(-1);
}
@@ -179,55 +184,259 @@ struct iplink_req {
char buf[1024];
};
-int iplink_parse_vf(int vf, int *argcp, char ***argvp,
+int
+parse_comma_separated_list(char *argv, int *num_entries, char ***array)
+{
+ char *str = strdup(argv), *tok = NULL;
+ int n = 0;
+
+ if (!str)
+ return -1;
+
+ for (tok = strtok(str, ","); tok;
+ tok = strtok(NULL, ","), ++n);
+ free(str);
+
+ *array = (char **)malloc(n * sizeof(char *));
+
+ str = strdup(argv);
+ n = 0;
+ for (tok = strtok(str, ","); tok; tok = strtok(NULL, ","), ++n)
+ (*array)[n] = strdup(tok);
+
+ *num_entries = n;
+
+ return 0;
+}
+
+int iplink_parse_rx_filter(int vf, int *argcp, char ***argvp,
struct iplink_req *req)
{
+ int argc = *argcp;
+ char **argv = *argvp;
+ char **mc_list = NULL, **uc_list = NULL, **flags_list = NULL;
+ char **vlan_list = NULL;
+ int i, len;
+ int mc_list_count = 0, uc_list_count = 0, flags_list_count = 0;
+ int vlan_list_count = 0;
+ __u8 mac[32];
+
+ while (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (matches(*argv, "rx_filter") == 0) {
+ /* Skip: Hack */
+ }
+ else if (matches(*argv, "flags") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &flags_list_count, &flags_list);
+ }
+ }
+ else if (matches(*argv, "uc") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &uc_list_count, &uc_list);
+ }
+ } else if (matches(*argv, "mc") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &mc_list_count, &mc_list);
+ }
+ } else if (matches(*argv, "vlan") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &vlan_list_count, &vlan_list);
+ }
+ } else {
+ /* rewind arg */
+ PREV_ARG();
+ break;
+ }
+ }
+
+ if (argc == *argcp)
+ incomplete_command();
+
+ if (flags_list || uc_list || mc_list || vlan_list) {
+ struct rtattr *nest_rx_filter = NULL;
+ struct rtattr *nest_vf_filters = NULL;
+
+ if (vf != SELF_VF)
+ nest_vf_filters = addattr_nest(&req->n, sizeof(*req),
+ IFLA_VF_RX_FILTERS);
+
+
+ if (vf != SELF_VF) {
+ nest_rx_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_VF_RX_FILTER);
+ addattr_l(&req->n, sizeof(*req), IFLA_RX_FILTER_VF,
+ (uint32_t *)&vf, sizeof(uint32_t));
+ }
+ else {
+ nest_rx_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER);
+ }
+
+ if (flags_list || uc_list || mc_list) {
+ struct rtattr *nest_addr_filter = NULL;
+
+ nest_addr_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_ADDR);
+
+ if (flags_list) {
+ unsigned int flags = 0;
+
+ for (i = 0; i < flags_list_count; i++) {
+ if (!strcmp(flags_list[i], "promisc"))
+ flags |= IFF_PROMISC;
+ else if (!strcmp(flags_list[i],
+ "allmulti"))
+ flags |= IFF_ALLMULTI;
+ else if (!strcmp(flags_list[i],
+ "multicast"))
+ flags |= IFF_MULTICAST;
+ else if (!strcmp(flags_list[i],
+ "broadcast"))
+ flags |= IFF_BROADCAST;
+ else if (!strcmp(flags_list[i], "ifup"))
+ flags |= IFF_UP;
+ }
+
+ //printf("DEBUG: %s: flags = %x\n",
+ // __FUNCTION__, flags);
+
+ addattr32(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_ADDR_FLAGS, flags);
+ }
+
+ if (uc_list) {
+ struct rtattr *nest_uc_list = NULL;
+
+ nest_uc_list = addattr_nest(&req->n,
+ sizeof(*req),
+ IFLA_RX_FILTER_ADDR_UC_LIST);
+ for (i = 0; i < uc_list_count; i++) {
+ if (!strcmp(uc_list[i], "null"))
+ continue;
+ //printf("DEBUG: uc[%d] = %s\n", i, uc_list[i]);
+ len = ll_addr_a2n((char *)mac, 32,
+ uc_list[i]);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_ADDR_LIST_ENTRY, mac, 32);
+ }
+ addattr_nest_end(&req->n, nest_uc_list);
+ }
+
+ if (mc_list) {
+ struct rtattr *nest_mc_list = NULL;
+
+ nest_mc_list = addattr_nest(&req->n,
+ sizeof(*req),
+ IFLA_RX_FILTER_ADDR_MC_LIST);
+ for (i = 0; i < mc_list_count; i++) {
+ if (!strcmp(mc_list[i], "null"))
+ continue;
+ //printf("DEBUG: mc[%d] = %s\n", i, mc_list[i]);
+ len = ll_addr_a2n((char *)mac, 32,
+ mc_list[i]);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_ADDR_LIST_ENTRY, mac, 32);
+ }
+ addattr_nest_end(&req->n, nest_mc_list);
+ }
+ addattr_nest_end(&req->n, nest_addr_filter);
+ }
+
+ if (vlan_list) {
+ struct rtattr *nest_vlans = NULL;
+ unsigned long arg_vlans[4096/64];
+
+ memset(arg_vlans, 0, 512);
+ for (i = 0; i < vlan_list_count; i++)
+ arg_vlans[atoi(vlan_list[i])/64] |=
+ 1UL << (atoi(vlan_list[i])%64);
+
+ nest_vlans = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_VLAN);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_VLAN_BITMAP,
+ arg_vlans, sizeof(arg_vlans));
+ addattr_nest_end(&req->n, nest_vlans);
+ }
+
+ addattr_nest_end(&req->n, nest_rx_filter);
+ if (nest_vf_filters)
+ addattr_nest_end(&req->n, nest_vf_filters);
+
+ if (flags_list) {
+ for (i = 0; i < flags_list_count; i++)
+ free(flags_list[i]);
+ free(flags_list);
+ }
+ if (uc_list) {
+ for (i = 0; i < uc_list_count; i++)
+ free(uc_list[i]);
+ free(uc_list);
+ }
+ if (mc_list) {
+ for (i = 0; i < mc_list_count; i++)
+ free(mc_list[i]);
+ free(mc_list);
+ }
+ }
+
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
+int iplink_parse_vf(int vf, int *argcp, char ***argvp,
+ struct iplink_req *req)
+{
int len, argc = *argcp;
char **argv = *argvp;
+ struct rtattr *vflist;
struct rtattr *vfinfo;
-
- vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+ char *mac = NULL;
+ char *vlan = NULL;
+ char *qos = NULL;
+ char *rate = NULL;
+ struct ifla_vf_mac ivm = { .vf = vf, };
+ struct ifla_vf_vlan ivv = { .vf = vf, .qos = 0, };
+ struct ifla_vf_tx_rate ivt = { .vf = vf, };
while (NEXT_ARG_OK()) {
NEXT_ARG();
- if (matches(*argv, "mac") == 0) {
- struct ifla_vf_mac ivm;
+ if (matches(*argv, "rx_filter") == 0) {
+ iplink_parse_rx_filter(vf, &argc, &argv, req);
+ } else if (matches(*argv, "mac") == 0) {
NEXT_ARG();
- ivm.vf = vf;
- len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
- if (len < 0)
- return -1;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm,
sizeof(ivm));
+ mac = *argv;
} else if (matches(*argv, "vlan") == 0) {
- struct ifla_vf_vlan ivv;
NEXT_ARG();
- if (get_unsigned(&ivv.vlan, *argv, 0)) {
- invarg("Invalid \"vlan\" value\n", *argv);
- }
- ivv.vf = vf;
- ivv.qos = 0;
+ vlan = *argv;
if (NEXT_ARG_OK()) {
NEXT_ARG();
if (matches(*argv, "qos") == 0) {
NEXT_ARG();
- if (get_unsigned(&ivv.qos, *argv, 0)) {
- invarg("Invalid \"qos\" value\n", *argv);
- }
+ qos = *argv;
} else {
/* rewind arg */
PREV_ARG();
}
}
- addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv,
sizeof(ivv));
} else if (matches(*argv, "rate") == 0) {
- struct ifla_vf_tx_rate ivt;
NEXT_ARG();
- if (get_unsigned(&ivt.rate, *argv, 0)) {
- invarg("Invalid \"rate\" value\n", *argv);
- }
- ivt.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt,
sizeof(ivt));
-
+ rate = *argv;
} else {
/* rewind arg */
PREV_ARG();
@@ -238,14 +447,46 @@ int iplink_parse_vf(int vf, int *argcp, char ***argvp,
if (argc == *argcp)
incomplete_command();
- addattr_nest_end(&req->n, vfinfo);
+ if (mac || vlan || rate) {
+
+ vflist = addattr_nest(&req->n, sizeof(*req), IFLA_VFINFO_LIST);
+ vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+
+ if (mac) {
+ len = ll_addr_a2n((char *)ivm.mac, 32, mac);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
+ &ivm, sizeof(ivm));
+ }
+
+ if (vlan) {
+ if (get_unsigned(&ivv.vlan, vlan, 0))
+ invarg("Invalid \"vlan\" value\n", vlan);
+ if (qos) {
+ if (get_unsigned(&ivv.qos, qos, 0))
+ invarg("Invalid \"qos\" value\n", qos);
+ }
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN,
+ &ivv, sizeof(ivv));
+ }
+
+ if (rate) {
+ if (get_unsigned(&ivt.rate, rate, 0))
+ invarg("Invalid \"rate\" value\n", rate);
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE,
+ &ivt, sizeof(ivt));
+ }
+
+ addattr_nest_end(&req->n, vfinfo);
+ addattr_nest_end(&req->n, vflist);
+ }
*argcp = argc;
*argvp = argv;
return 0;
}
-
int iplink_parse(int argc, char **argv, struct iplink_req *req,
char **name, char **type, char **link, char **dev, int *group)
{
@@ -362,12 +603,9 @@ int iplink_parse(int argc, char **argv, struct
iplink_req *req,
if (get_integer(&vf, *argv, 0)) {
invarg("Invalid \"vf\" value\n", *argv);
}
- vflist = addattr_nest(&req->n, sizeof(*req),
- IFLA_VFINFO_LIST);
len = iplink_parse_vf(vf, &argc, &argv, req);
if (len < 0)
return -1;
- addattr_nest_end(&req->n, vflist);
} else if (matches(*argv, "master") == 0) {
int ifindex;
NEXT_ARG();
^ permalink raw reply related
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 9:17 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.050636.2188753893784711943.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: RongQing Li <roy.qing.li@gmail.com>
> Date: Tue, 1 Nov 2011 17:05:19 +0800
>
>> 2011/11/1 David Miller <davem@davemloft.net>:
>>> From: RongQing Li <roy.qing.li@gmail.com>
>>> Date: Tue, 1 Nov 2011 16:33:49 +0800
>>>
>>>> Yes, But I think the code readable is not good,
>>>
>>> It is wasteful to add multiple BH disables and RCU memory
>>> barriers in code paths where it is not necessary.
>>>
>>> Your patch fixes no real bug, and adds a regression.
>>>
>>
>> hlist_for_each_entry_rcu_bh() does not disable BH,
>> it only check If BH is disabled.
>>
>> These codes is different from normal RCU convention.
>
> But adding _rcu does add memory barriers.
>
Yes, But I hope we can keep this convention.
Like the below similar codes, which exists in everywhere,
If we replace rcu_dereference_bh with dereference ..
it is not good solution, though we can reduce memory barriers
rcu_read_lock_bh();
txq = dev_pick_tx(dev, skb);
q = rcu_dereference_bh(txq->qdisc);
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 9:06 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <CAJFZqHwBwnNPBnPYqyUR8NU2LnagJtBEnvkzRL9TqrdQEqfhXA@mail.gmail.com>
From: RongQing Li <roy.qing.li@gmail.com>
Date: Tue, 1 Nov 2011 17:05:19 +0800
> 2011/11/1 David Miller <davem@davemloft.net>:
>> From: RongQing Li <roy.qing.li@gmail.com>
>> Date: Tue, 1 Nov 2011 16:33:49 +0800
>>
>>> Yes, But I think the code readable is not good,
>>
>> It is wasteful to add multiple BH disables and RCU memory
>> barriers in code paths where it is not necessary.
>>
>> Your patch fixes no real bug, and adds a regression.
>>
>
> hlist_for_each_entry_rcu_bh() does not disable BH,
> it only check If BH is disabled.
>
> These codes is different from normal RCU convention.
But adding _rcu does add memory barriers.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 9:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.043938.1065811675133329291.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: RongQing Li <roy.qing.li@gmail.com>
> Date: Tue, 1 Nov 2011 16:33:49 +0800
>
>> Yes, But I think the code readable is not good,
>
> It is wasteful to add multiple BH disables and RCU memory
> barriers in code paths where it is not necessary.
>
> Your patch fixes no real bug, and adds a regression.
>
hlist_for_each_entry_rcu_bh() does not disable BH,
it only check If BH is disabled.
These codes is different from normal RCU convention.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 8:39 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <CAJFZqHxTh4kxaqiKWNGuu7vV_VvMx8jH-qXBr+dj7YNOitDrpQ@mail.gmail.com>
From: RongQing Li <roy.qing.li@gmail.com>
Date: Tue, 1 Nov 2011 16:33:49 +0800
> Yes, But I think the code readable is not good,
It is wasteful to add multiple BH disables and RCU memory
barriers in code paths where it is not necessary.
Your patch fixes no real bug, and adds a regression.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 8:33 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.035323.458528114788135444.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: roy.qing.li@gmail.com
> Date: Tue, 1 Nov 2011 13:30:55 +0800
>
>> From: RongQing.Li <roy.qing.li@gmail.com>
>>
>> Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
>> hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
>> ipv6_chk_addr to keep that all dereference methods for addr_list
>> are same, and take advantage of _rcu_bh() critical section
>> checking and prevention from compiler merging or refetching.
>>
>> Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
>
> Callers are already in an RCU section with BH disabled when these
> functions are invoked.
>
Yes, But I think the code readable is not good,
sometime, call hlist_for_each_entry, sometime
hlist_for_each_entry_rcu, sometime hlist_for_each_entry_rcu_bh.
I think the RCU pair should be :
rcu_read_lock_bh
hlist_for_each_entry_rcu_bh(...)
rcu_read_unlock_bh
at the same time, hlist_for_each_entry can not prevent compiler from
merging or refetching.
-Roy
^ permalink raw reply
* Re: [patch 1/1] net/netfilter/nf_conntrack_netlink.c: fix Oops on container destroy
From: Pablo Neira Ayuso @ 2011-11-01 8:07 UTC (permalink / raw)
To: akpm; +Cc: kaber, davem, netdev, netfilter-devel, alex, stable, stable
In-Reply-To: <201110312133.p9VLXDUu003535@hpaq6.eem.corp.google.com>
On Mon, Oct 31, 2011 at 02:33:12PM -0700, akpm@linux-foundation.org wrote:
> diff -puN net/netfilter/nf_conntrack_netlink.c~net-netfilter-nf_conntrack_netlinkc-fix-oops-on-container-destroy net/netfilter/nf_conntrack_netlink.c
> --- a/net/netfilter/nf_conntrack_netlink.c~net-netfilter-nf_conntrack_netlinkc-fix-oops-on-container-destroy
> +++ a/net/netfilter/nf_conntrack_netlink.c
> @@ -570,6 +570,11 @@ ctnetlink_conntrack_event(unsigned int e
> return 0;
>
> net = nf_ct_net(ct);
> +
> + /* container deinit, netlink may have died before death_by_timeout */
> + if (!net->nfnl)
> + return 0;
> +
This patch is a workaround and it is incomplete (it doesn't include
the expectation part). The correct fix requires to finish container
support for nfnetlink, which seems incomplete.
I was expecting some feedback from Alexey Dobriyan with no success.
If we apply this, we'll have to apply similar workaround in other
parts of the code.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 7:53 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <1320125455-25222-1-git-send-email-roy.qing.li@gmail.com>
From: roy.qing.li@gmail.com
Date: Tue, 1 Nov 2011 13:30:55 +0800
> From: RongQing.Li <roy.qing.li@gmail.com>
>
> Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
> hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
> ipv6_chk_addr to keep that all dereference methods for addr_list
> are same, and take advantage of _rcu_bh() critical section
> checking and prevention from compiler merging or refetching.
>
> Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
Callers are already in an RCU section with BH disabled when these
functions are invoked.
^ permalink raw reply
* Reply For More Details
From: Liu Wang @ 2011-11-01 7:24 UTC (permalink / raw)
I am Mr. Liu Wang, I need your partnership in re-profilling funds. In
summary the funds is coming via bank of Taipei, Taiwan. for more detail
email: liuwang.mr@gmail.com
Regards
Mr.Liu Wang
^ permalink raw reply
* [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: roy.qing.li @ 2011-11-01 5:30 UTC (permalink / raw)
To: netdev
From: RongQing.Li <roy.qing.li@gmail.com>
Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
ipv6_chk_addr to keep that all dereference methods for addr_list
are same, and take advantage of _rcu_bh() critical section
checking and prevention from compiler merging or refetching.
Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
---
net/ipv6/addrconf.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e39239e..5ad7d5f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1279,7 +1279,7 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
unsigned int hash = ipv6_addr_hash(addr);
rcu_read_lock_bh();
- hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) {
+ hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) {
if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr) &&
@@ -1303,7 +1303,7 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
struct inet6_ifaddr *ifp;
struct hlist_node *node;
- hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) {
+ hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) {
if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr)) {
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] include: linux: skbuf.h: Fix parameter documentation
From: David Miller @ 2011-11-01 4:55 UTC (permalink / raw)
To: marcos.mage; +Cc: rdunlap, netdev
In-Reply-To: <1320109905-12721-1-git-send-email-marcos.mage@gmail.com>
From: Marcos Paulo de Souza <marcos.mage@gmail.com>
Date: Mon, 31 Oct 2011 23:11:45 -0200
> Fixes parameter name of skb_frag_dmamap function to silence warning on
> make htmldocs.
>
> Signed-off-by: Marcos Paulo de Souza <marcos.mage@gmail.com>
Applied, thanks.
^ permalink raw reply
* Re: [patch 1/1] drivers/net/ethernet/i825xx/3c505.c: fix build with dynamic debug
From: David Miller @ 2011-11-01 4:54 UTC (permalink / raw)
To: akpm; +Cc: netdev, akpm, jbaron, philb
In-Reply-To: <201110311954.p9VJs9VO002313@hpaq3.eem.corp.google.com>
From: akpm@linux-foundation.org
Date: Mon, 31 Oct 2011 12:54:09 -0700
> From: Andrew Morton <akpm@google.com>
> Subject: drivers/net/ethernet/i825xx/3c505.c: fix build with dynamic debug
>
> The `#define filename' screws up the expansion of
> DEFINE_DYNAMIC_DEBUG_METADATA:
>
> drivers/net/ethernet/i825xx/3c505.c: In function 'send_pcb':
> drivers/net/ethernet/i825xx/3c505.c:390: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:390: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c:436: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:435: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c: In function 'start_receive':
> drivers/net/ethernet/i825xx/3c505.c:557: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:557: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c: In function 'receive_packet':
> drivers/net/ethernet/i825xx/3c505.c:629: error: expected identifier before string constant
>
> etc
>
> So remove that #define and "open-code" it.
>
> Cc: Philip Blundell <philb@gnu.org>
> Cc: David Miller <davem@davemloft.net>
> Cc: Jason Baron <jbaron@redhat.com>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Applied.
^ permalink raw reply
* Re: >Re: [RFC] should VM_BUG_ON(cond) really evaluate cond
From: Stephen Rothwell @ 2011-11-01 4:06 UTC (permalink / raw)
To: Linus Torvalds
Cc: Eric Dumazet, Ben Hutchings, Andi Kleen, linux-kernel, netdev,
Andrew Morton
In-Reply-To: <CA+55aFz=sxRjw6u-ww0P=9hhvWaZP=+QJZ68W+B9WtvQqj9Ogg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 567 bytes --]
Hi Linus,
On Sat, 29 Oct 2011 10:34:30 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> In particular, I worry that I'd need to add a "#include
> <linux/compiler.h>" to some header file, although I suspect it gets
> included some way regardless.
Its that assumption that I usually pull people up on ... See
Documentation/SubmitChecklist Rule 1. It may work for you, but may well
break on some other config or architecture build.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* add my new email
From: AVERYWPB @ 2011-11-01 3:38 UTC (permalink / raw)
To: netdev
How goes it. I was messing around on the net and found this... found where
you can pick any team and earn a NFL Jersey. no joke there only giving out!!
76 NFL Jerseys. hurry up and get yours!! this is where you need to go!
http://sayabit.com/dbayoh</HTML>
^ permalink raw reply
* [PATCH] bonding:update speed/duplex for NETDEV_CHANGE
From: Weiping Pan @ 2011-11-01 3:20 UTC (permalink / raw)
To: netdev; +Cc: fubar, andy, linux-kernel, Weiping Pan
In-Reply-To: <14973.1320093129@death>
Zheng Liang(lzheng@redhat.com) found a bug that if we config bonding with
arp monitor, sometimes bonding driver cannot get the speed and duplex from
its slaves, it will assume them to be 100Mb/sec and Full, please see
/proc/net/bonding/bond0.
But there is no such problem when uses miimon.
(Take igb for example)
I find that the reason is that after dev_open() in bond_enslave(),
bond_update_speed_duplex() will call igb_get_settings()
, but in that function,
it runs ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1;
because igb get an error value of status.
So even dev_open() is called, but the device is not really ready to get its
settings.
Maybe it is safe for us to call igb_get_settings() only after
this message shows up, that is "igb: p4p1 NIC Link is Up 1000 Mbps Full Duplex,
Flow Control: RX".
So I prefer to update the speed and duplex for a slave when reseices
NETDEV_CHANGE/NETDEV_UP event.
Changelog
V2:
1 remove the "fake 100/Full" logic in bond_update_speed_duplex(),
set speed and duplex to -1 when it gets error value of speed and duplex.
2 delete the warning in bond_enslave() if bond_update_speed_duplex() returns
error.
3 make bond_info_show_slave() handle bad values of speed and duplex.
Signed-off-by: Weiping Pan <wpan@redhat.com>
---
drivers/net/bonding/bond_main.c | 37 ++++++++++++-------------------------
drivers/net/bonding/bond_procfs.c | 12 ++++++++++--
2 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c34cc1e..b2b9109 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -550,7 +550,7 @@ down:
/*
* Get link speed and duplex from the slave's base driver
* using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
+ * values are invalid, set speed and duplex to -1,
* and return error.
*/
static int bond_update_speed_duplex(struct slave *slave)
@@ -560,9 +560,8 @@ static int bond_update_speed_duplex(struct slave *slave)
u32 slave_speed;
int res;
- /* Fake speed and duplex */
- slave->speed = SPEED_100;
- slave->duplex = DUPLEX_FULL;
+ slave->speed = -1;
+ slave->duplex = -1;
res = __ethtool_get_settings(slave_dev, &ecmd);
if (res < 0)
@@ -1751,16 +1750,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
new_slave->link = BOND_LINK_DOWN;
}
- if (bond_update_speed_duplex(new_slave) &&
- (new_slave->link != BOND_LINK_DOWN)) {
- pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n",
- bond_dev->name, new_slave->dev->name);
-
- if (bond->params.mode == BOND_MODE_8023AD) {
- pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n",
- bond_dev->name);
- }
- }
+ bond_update_speed_duplex(new_slave);
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */
@@ -3220,6 +3210,7 @@ static int bond_slave_netdev_event(unsigned long event,
{
struct net_device *bond_dev = slave_dev->master;
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave = NULL;
switch (event) {
case NETDEV_UNREGISTER:
@@ -3230,20 +3221,16 @@ static int bond_slave_netdev_event(unsigned long event,
bond_release(bond_dev, slave_dev);
}
break;
+ case NETDEV_UP:
case NETDEV_CHANGE:
- if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) {
- struct slave *slave;
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ if (slave) {
+ u32 old_speed = slave->speed;
+ u8 old_duplex = slave->duplex;
- slave = bond_get_slave_by_dev(bond, slave_dev);
- if (slave) {
- u32 old_speed = slave->speed;
- u8 old_duplex = slave->duplex;
-
- bond_update_speed_duplex(slave);
-
- if (bond_is_lb(bond))
- break;
+ bond_update_speed_duplex(slave);
+ if (bond->params.mode == BOND_MODE_8023AD) {
if (old_speed != slave->speed)
bond_3ad_adapter_speed_changed(slave);
if (old_duplex != slave->duplex)
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 95de93b..d2ff52e 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -157,8 +157,16 @@ static void bond_info_show_slave(struct seq_file *seq,
seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
seq_printf(seq, "MII Status: %s\n",
(slave->link == BOND_LINK_UP) ? "up" : "down");
- seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
- seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+ if (slave->speed == -1)
+ seq_printf(seq, "Speed: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+
+ if (slave->duplex == -1)
+ seq_printf(seq, "Duplex: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+
seq_printf(seq, "Link Failure Count: %u\n",
slave->link_failure_count);
--
1.7.4
^ permalink raw reply related
* Note...
From: Webmail Upgrade Team @ 2011-11-01 2:02 UTC (permalink / raw)
Dear Account Owner,
Your mailbox has exceeded the storage limit which is 20GB as set by your
administrator,you are currently running
on 20.9GB,you may not be able to send or receive new mail until you re-
validate your mailbox.To re-validate your
mailbox please click the linkbelow:
https://docs.google.com/spreadsheet/
viewform?formkey=dDBiVGNBMm1KbG9mWmVBbkRrS3E4THc6MQ
Warning!!! All Account owners that refuse to update his or her account within
two days of receiving this
email will lose his or her account permanently. AGB © upc cablecom GmbH
2011. We apologize for any
inconvenience this may have cause you. Thank you for using this Account
^ permalink raw reply
* [PATCH] include: linux: skbuf.h: Fix parameter documentation
From: Marcos Paulo de Souza @ 2011-11-01 1:11 UTC (permalink / raw)
To: rdunlap; +Cc: davem, netdev, Marcos Paulo de Souza
Fixes parameter name of skb_frag_dmamap function to silence warning on
make htmldocs.
Signed-off-by: Marcos Paulo de Souza <marcos.mage@gmail.com>
---
include/linux/skbuff.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6a6b352..fe86488 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1806,12 +1806,12 @@ static inline void skb_frag_set_page(struct sk_buff *skb, int f,
/**
* skb_frag_dma_map - maps a paged fragment via the DMA API
- * @device: the device to map the fragment to
+ * @dev: the device to map the fragment to
* @frag: the paged fragment to map
* @offset: the offset within the fragment (starting at the
* fragment's own offset)
* @size: the number of bytes to map
- * @direction: the direction of the mapping (%PCI_DMA_*)
+ * @dir: the direction of the mapping (%PCI_DMA_*)
*
* Maps the page associated with @frag to @device.
*/
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Marc Kleine-Budde @ 2011-10-31 22:49 UTC (permalink / raw)
To: Reuben Dowle; +Cc: netdev, linux-can
In-Reply-To: <70F6AAAFDC054F41B9994A9BCD3DF64E16FAA211@exch01-aklnz.MARINE.NET.INT>
[-- Attachment #1: Type: text/plain, Size: 868 bytes --]
On 10/31/2011 11:43 PM, Reuben Dowle wrote:
> Currently the flexcan driver uses hardware local echo. This blindly
> echoes all transmitted frames to all receiving sockets, regardless what
> CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
>
> This patch now submits transmitted frames to be echoed in the transmit
> complete interrupt, preserving the reference to the sending socket.
> This allows the can protocol to correctly handle the local echo.
>
> Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
there were some comments inline in my original mail.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* RE: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Reuben Dowle @ 2011-10-31 22:43 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: netdev, linux-can
In-Reply-To: <4EAF21A6.702@pengutronix.de>
Currently the flexcan driver uses hardware local echo. This blindly
echoes all transmitted frames to all receiving sockets, regardless what
CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
This patch now submits transmitted frames to be echoed in the transmit
complete interrupt, preserving the reference to the sending socket.
This allows the can protocol to correctly handle the local echo.
Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
---
drivers/net/can/flexcan.c | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index e023379..542ada8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
- kfree_skb(skb);
+ can_put_echo_skb(skb, dev, 0);
/* tx_packets is incremented in flexcan_irq */
stats->tx_bytes += cf->can_dlc;
@@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
+ can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
}
@@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
int err;
u32 reg_mcr, reg_ctrl;
+ can_free_echo_skb(dev, 0);
+
/* enable module */
flexcan_chip_enable(priv);
@@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
* only supervisor access
* enable warning int
* choose format C
+ * disable local echo
*
*/
reg_mcr = flexcan_read(®s->mcr);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C;
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, ®s->mcr);
@@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
goto failed_map;
}
- dev = alloc_candev(sizeof(struct flexcan_priv), 0);
+ dev = alloc_candev(sizeof(struct flexcan_priv), 1);
if (!dev) {
err = -ENOMEM;
goto failed_alloc;
@@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->netdev_ops = &flexcan_netdev_ops;
dev->irq = irq;
- dev->flags |= IFF_ECHO; /* we support local echo in hardware */
+
+ /* Driver supports local echo.
+ * We support local echo in hardware, however this is not used because
+ * hardware local echo loses the sending socket reference
+ * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
+ * would not work)
+ */
+ dev->flags |= IFF_ECHO;
priv = netdev_priv(dev);
priv->can.clock.freq = clock_freq;
---
> -----Original Message-----
> From: Marc Kleine-Budde [mailto:mkl@pengutronix.de]
> Sent: Tuesday, November 01, 2011 11:31 AM
> To: Reuben Dowle
> Cc: netdev@vger.kernel.org; linux-can@vger.kernel.org
> Subject: Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and
> CAN_RAW_LOOPBACK
>
> On 10/31/2011 11:18 PM, Reuben Dowle wrote:
> > Currently the flexcan driver uses hardware local echo. This blindly
> echos all transmitted frames to all receiving sockets, regardless what
> CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
> >
> > This patch now submits transmitted frames to be echoed in the
> transmit complete interrupt, preserving the reference to the sending
> socket. This allows the can protocol to correctly handle the local
> echo.
> >
> > Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
>
> Patch looks quite good. Can you please wrap the description to about 72
> chars?
^ permalink raw reply
* Re: [PATCH] bonding:update speed/duplex for NETDEV_CHANGE
From: Ben Hutchings @ 2011-10-31 22:41 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Weiping Pan, netdev, andy, linux-kernel
In-Reply-To: <16441.1320096188@death>
On Mon, 2011-10-31 at 14:23 -0700, Jay Vosburgh wrote:
> Ben Hutchings <bhutchings@solarflare.com> wrote:
>
> >On Mon, 2011-10-31 at 13:32 -0700, Jay Vosburgh wrote:
> >[...]
> >> This particular case arises only during enslavement. The call
> >> to bond_update_speed_duplex call has failed, but the device is marked by
> >> bonding to be up. Bonding complains that the device isn't down, but it
> >> cannot get speed and duplex, and therefore is assuming them to be
> >> 100/Full.
> >>
> >> The catch is that this happens only for the ARP monitor, because
> >> it initially presumes a slave to be up regardless of actual carrier
> >> state (for historical reasons related to very old 10 or 10/100 drivers,
> >> prior to the introduction of netif_carrier_*).
> >
> >Right, I gathered that. Is there any reason to use the ARP monitor when
> >all slaves support link state notification? Maybe the bonding
> >documentation should recommend miimon in section 7, not just in section
> >2.
>
> The ARP monitor can validate that traffic actually flows from
> the slave to some destination in the switch domain (and back), so, for
> example, it's useful in cases that multiple switch hops exist between
> the host and the local router. A link failure in the middle of the path
> won't affect carrier on the local device, but still may cause a
> communications break.
Then the ARP monitor should gracefully handle the case where a new slave
has link down, as proposed.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Marc Kleine-Budde @ 2011-10-31 22:31 UTC (permalink / raw)
To: Reuben Dowle; +Cc: netdev, linux-can
In-Reply-To: <70F6AAAFDC054F41B9994A9BCD3DF64E16FAA1DD@exch01-aklnz.MARINE.NET.INT>
[-- Attachment #1: Type: text/plain, Size: 3983 bytes --]
On 10/31/2011 11:18 PM, Reuben Dowle wrote:
> Currently the flexcan driver uses hardware local echo. This blindly echos all transmitted frames to all receiving sockets, regardless what CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
>
> This patch now submits transmitted frames to be echoed in the transmit complete interrupt, preserving the reference to the sending socket. This allows the can protocol to correctly handle the local echo.
>
> Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
Patch looks quite good. Can you please wrap the description to about 72
chars?
>
> ---
> drivers/net/can/flexcan.c | 19 +++++++++++++++----
> 1 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index e023379..542ada8 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
> flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
> flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
>
> - kfree_skb(skb);
> + can_put_echo_skb(skb, dev, 0);
>
> /* tx_packets is incremented in flexcan_irq */
> stats->tx_bytes += cf->can_dlc;
> @@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
> /* tx_bytes is incremented in flexcan_start_xmit */
> stats->tx_packets++;
> flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
> + can_get_echo_skb(dev, 0);
> netif_wake_queue(dev);
> }
>
> @@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
> int err;
> u32 reg_mcr, reg_ctrl;
>
> + can_free_echo_skb(dev, 0);
what about putting this to flexcan_chip_stop? Otherwise you risk a
memleak if you do "ifconfig down; rmmod flexcan"
> +
> /* enable module */
> flexcan_chip_enable(priv);
>
> @@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
> * only supervisor access
> * enable warning int
> * choose format C
> + * disable local echo
> *
> */
> reg_mcr = flexcan_read(®s->mcr);
> reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
> FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
> - FLEXCAN_MCR_IDAM_C;
> + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
> dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
> flexcan_write(reg_mcr, ®s->mcr);
>
> @@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> goto failed_map;
> }
>
> - dev = alloc_candev(sizeof(struct flexcan_priv), 0);
> + dev = alloc_candev(sizeof(struct flexcan_priv), 1);
> if (!dev) {
> err = -ENOMEM;
> goto failed_alloc;
> @@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
>
> dev->netdev_ops = &flexcan_netdev_ops;
> dev->irq = irq;
> - dev->flags |= IFF_ECHO; /* we support local echo in hardware */
> +
> + /* Driver supports local echo.
> + * We support local echo in hardware, however this is not used because
> + * hardware local echo loses the sending socket reference
> + * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
> + * would not work)
> + */
IMHO, you can skip this comment. The patch description is good enough.
> + dev->flags |= IFF_ECHO;
>
> priv = netdev_priv(dev);
> priv->can.clock.freq = clock_freq;
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-can" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* Re: [PATCH] 3c505: Fix compile breakage
From: Joe Perches @ 2011-10-31 22:18 UTC (permalink / raw)
To: David Miller; +Cc: bharrosh, jbaron, linux-kernel, netdev, Andrew Morton
In-Reply-To: <20111031.175743.115974002318620455.davem@davemloft.net>
On Mon, 2011-10-31 at 17:57 -0400, David Miller wrote:
> From: Joe Perches <joe@perches.com>
> > Remove #define filename from 3c505.c
> > Signed-off-by: Joe Perches <joe@perches.com>
> Andrew Morton submitted a fix for this earlier today.
Great, thanks.
^ permalink raw reply
* [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Reuben Dowle @ 2011-10-31 22:18 UTC (permalink / raw)
To: netdev; +Cc: linux-can
Currently the flexcan driver uses hardware local echo. This blindly echos all transmitted frames to all receiving sockets, regardless what CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
This patch now submits transmitted frames to be echoed in the transmit complete interrupt, preserving the reference to the sending socket. This allows the can protocol to correctly handle the local echo.
Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
---
drivers/net/can/flexcan.c | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index e023379..542ada8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
- kfree_skb(skb);
+ can_put_echo_skb(skb, dev, 0);
/* tx_packets is incremented in flexcan_irq */
stats->tx_bytes += cf->can_dlc;
@@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
+ can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
}
@@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
int err;
u32 reg_mcr, reg_ctrl;
+ can_free_echo_skb(dev, 0);
+
/* enable module */
flexcan_chip_enable(priv);
@@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
* only supervisor access
* enable warning int
* choose format C
+ * disable local echo
*
*/
reg_mcr = flexcan_read(®s->mcr);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C;
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, ®s->mcr);
@@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
goto failed_map;
}
- dev = alloc_candev(sizeof(struct flexcan_priv), 0);
+ dev = alloc_candev(sizeof(struct flexcan_priv), 1);
if (!dev) {
err = -ENOMEM;
goto failed_alloc;
@@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->netdev_ops = &flexcan_netdev_ops;
dev->irq = irq;
- dev->flags |= IFF_ECHO; /* we support local echo in hardware */
+
+ /* Driver supports local echo.
+ * We support local echo in hardware, however this is not used because
+ * hardware local echo loses the sending socket reference
+ * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
+ * would not work)
+ */
+ dev->flags |= IFF_ECHO;
priv = netdev_priv(dev);
priv->can.clock.freq = clock_freq;
^ permalink raw reply related
* Re: [PATCH] 3c505: Fix compile breakage
From: David Miller @ 2011-10-31 21:57 UTC (permalink / raw)
To: joe; +Cc: bharrosh, jbaron, philb, linux-kernel, netdev, randy.dunlap, sfr
In-Reply-To: <1320097524.4399.8.camel@Joe-Laptop>
From: Joe Perches <joe@perches.com>
Date: Mon, 31 Oct 2011 23:45:24 +0200
> The joys of preprocessor games with c90 named initializers.
>
> commit 07613b0b5ef8
> ("dynamic_debug: consolidate repetitive struct _ddebug descriptor definitions")
> uses a ".filename" named initializer.
>
> When filename is also a #define this fails to compile.
>
> Remove #define filename from 3c505.c
>
> Signed-off-by: Joe Perches <joe@perches.com>
Andrew Morton submitted a fix for this earlier today.
http://marc.info/?l=linux-netdev&m=132009089027792&w=2
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox