* Re: [iproute PATCH] lib/bpf: Fix bytecode-file parsing
From: Daniel Borkmann @ 2017-08-30 13:53 UTC (permalink / raw)
To: Phil Sutter, Stephen Hemminger; +Cc: netdev
In-Reply-To: <20170829150945.7077-1-phil@nwl.cc>
On 08/29/2017 05:09 PM, Phil Sutter wrote:
> The signedness of char type is implementation dependent, and there are
> architectures on which it is unsigned by default. In that case, the
> check whether fgetc() returned EOF failed because the return value was
> assigned an (unsigned) char variable prior to comparison with EOF (which
> is defined to -1). Fix this by using int as type for 'c' variable, which
> also matches the declaration of fgetc().
>
> While being at it, fix the parser logic to correctly handle multiple
> empty lines and consecutive whitespace and tab characters to further
> improve the parser's robustness. Note that this will still detect double
> separator characters, so doesn't soften up the parser too much.
>
> Fixes: 3da3ebfca85b8 ("bpf: Make bytecode-file reading a little more robust")
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Definitely ack on the EOF bug:
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
[...]
> @@ -228,18 +229,20 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
> case '\n':
> if (c_prev != ',')
> *(pos++) = ',';
> + c_prev = ',';
> break;
> case ' ':
> case '\t':
> if (c_prev != ' ')
> *(pos++) = c;
> + c_prev = ' ';
> break;
> default:
> *(pos++) = c;
> + c_prev = c;
> }
> if (pos - tmp_string == tmp_len)
> break;
> - c_prev = c;
I don't really have a strong opinion on this, but the logic for
normalizing here is getting a bit convoluted. Is your use case
for making the parser more robust mainly so you can just use the
-ddd output from tcpdump for cBPF w/o piping through tr? But even
that shouldn't give multiple empty lines afaik, no?
^ permalink raw reply
* Re: [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload
From: kbuild test robot @ 2017-08-30 13:46 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-4-tom@quantonium.net>
[-- Attachment #1: Type: text/plain, Size: 5484 bytes --]
Hi Tom,
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/flow_dissector-Protocol-specific-flow-dissector-offload/20170830-210709
config: x86_64-randconfig-x006-201735 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
net//ipv4/route.c: In function 'fib_multipath_hash':
>> net//ipv4/route.c:1817:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
struct flow_keys keys;
^~~~~~
vim +1817 net//ipv4/route.c
79a13159 Peter Nørlund 2015-09-30 1791
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1792 /* if skb is set it will be used and fl4 can be NULL */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1793 int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1794 const struct sk_buff *skb)
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1795 {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1796 struct net *net = fi->fib_net;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1797 struct flow_keys hash_keys;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1798 u32 mhash;
79a13159 Peter Nørlund 2015-09-30 1799
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1800 switch (net->ipv4.sysctl_fib_multipath_hash_policy) {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1801 case 0:
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1802 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1803 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1804 if (skb) {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1805 ip_multipath_l3_keys(skb, &hash_keys);
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1806 } else {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1807 hash_keys.addrs.v4addrs.src = fl4->saddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1808 hash_keys.addrs.v4addrs.dst = fl4->daddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1809 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1810 break;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1811 case 1:
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1812 /* skb is currently provided only when forwarding */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1813 if (skb) {
19a7c5ba Tom Herbert 2017-08-29 1814 unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP |
19a7c5ba Tom Herbert 2017-08-29 1815 FLOW_DISSECTOR_F_STOP_AT_L4;
19a7c5ba Tom Herbert 2017-08-29 1816 ;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 @1817 struct flow_keys keys;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1818
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1819 /* short-circuit if we already have L4 hash present */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1820 if (skb->l4_hash)
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1821 return skb_get_hash_raw(skb) >> 1;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1822 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1823 skb_flow_dissect_flow_keys(skb, &keys, flag);
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1824 hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1825 hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1826 hash_keys.ports.src = keys.ports.src;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1827 hash_keys.ports.dst = keys.ports.dst;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1828 hash_keys.basic.ip_proto = keys.basic.ip_proto;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1829 } else {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1830 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1831 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1832 hash_keys.addrs.v4addrs.src = fl4->saddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1833 hash_keys.addrs.v4addrs.dst = fl4->daddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1834 hash_keys.ports.src = fl4->fl4_sport;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1835 hash_keys.ports.dst = fl4->fl4_dport;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1836 hash_keys.basic.ip_proto = fl4->flowi4_proto;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1837 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1838 break;
79a13159 Peter Nørlund 2015-09-30 1839 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1840 mhash = flow_hash_from_keys(&hash_keys);
79a13159 Peter Nørlund 2015-09-30 1841
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1842 return mhash >> 1;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1843 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1844 EXPORT_SYMBOL_GPL(fib_multipath_hash);
79a13159 Peter Nørlund 2015-09-30 1845 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
79a13159 Peter Nørlund 2015-09-30 1846
:::::: The code at line 1817 was first introduced by commit
:::::: bf4e0a3db97eb882368fd82980b3b1fa0b5b9778 net: ipv4: add support for ECMP hash policy choice
:::::: TO: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 35395 bytes --]
^ permalink raw reply
* Re: [PATCH][next][V2] bpf: test_maps: fix typo "conenct" -> "connect"
From: Daniel Borkmann @ 2017-08-30 13:46 UTC (permalink / raw)
To: Colin King, Alexei Starovoitov, Shuah Khan, netdev,
linux-kselftest
Cc: linux-kernel
In-Reply-To: <20170830114730.28550-1-colin.king@canonical.com>
On 08/30/2017 01:47 PM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Trivial fix to typo in printf error message
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
For net-next; looks like there is also one in "failed to listeen\n".
Want to fix this one as well ? ;)
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* [PATCH net-next v7] openvswitch: enable NSH support
From: Yi Yang @ 2017-08-30 12:39 UTC (permalink / raw)
To: netdev; +Cc: davem, dev, jbenc, e, blp, jan.scheurich, Yi Yang
v6->v7
- Remove NSH GSO patches in v6 because Jiri Benc
reworked it as another patch series and they have
been merged.
- Change it to adapt to nsh kernel module added by NSH
GSO patch series
v5->v6
- Fix the rest comments for v4.
- Add NSH GSO support for VxLAN-gpe + NSH and
Eth + NSH.
v4->v5
- Fix many comments by Jiri Benc and Eric Garver
for v4.
v3->v4
- Add new NSH match field ttl
- Update NSH header to the latest format
which will be final format and won't change
per its author's confirmation.
- Fix comments for v3.
v2->v3
- Change OVS_KEY_ATTR_NSH to nested key to handle
length-fixed attributes and length-variable
attriubte more flexibly.
- Remove struct ovs_action_push_nsh completely
- Add code to handle nested attribute for SET_MASKED
- Change PUSH_NSH to use the nested OVS_KEY_ATTR_NSH
to transfer NSH header data.
- Fix comments and coding style issues by Jiri and Eric
v1->v2
- Change encap_nsh and decap_nsh to push_nsh and pop_nsh
- Dynamically allocate struct ovs_action_push_nsh for
length-variable metadata.
OVS master and 2.8 branch has merged NSH userspace
patch series, this patch is to enable NSH support
in kernel data path in order that OVS can support
NSH in compat mode by porting this.
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
---
include/net/nsh.h | 3 +
include/uapi/linux/openvswitch.h | 28 +++
net/nsh/nsh.c | 41 ++++
net/openvswitch/actions.c | 141 ++++++++++++++
net/openvswitch/flow.c | 55 ++++++
net/openvswitch/flow.h | 11 ++
net/openvswitch/flow_netlink.c | 406 ++++++++++++++++++++++++++++++++++++++-
net/openvswitch/flow_netlink.h | 4 +
8 files changed, 688 insertions(+), 1 deletion(-)
diff --git a/include/net/nsh.h b/include/net/nsh.h
index a1eaea2..6c0cd57 100644
--- a/include/net/nsh.h
+++ b/include/net/nsh.h
@@ -304,4 +304,7 @@ static inline void nsh_set_flags_ttl_len(struct nshhdr *nsh, u8 flags,
NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
}
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nsh_src,
+ bool is_eth);
+
#endif /* __NET_NSH_H */
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 156ee4c..91dee5b 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -333,6 +333,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4, /* struct ovs_key_ct_tuple_ipv4 */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6, /* struct ovs_key_ct_tuple_ipv6 */
+ OVS_KEY_ATTR_NSH, /* Nested set of ovs_nsh_key_* */
#ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */
@@ -491,6 +492,29 @@ struct ovs_key_ct_tuple_ipv6 {
__u8 ipv6_proto;
};
+enum ovs_nsh_key_attr {
+ OVS_NSH_KEY_ATTR_BASE, /* struct ovs_nsh_key_base. */
+ OVS_NSH_KEY_ATTR_MD1, /* struct ovs_nsh_key_md1. */
+ OVS_NSH_KEY_ATTR_MD2, /* variable-length octets for MD type 2. */
+ __OVS_NSH_KEY_ATTR_MAX
+};
+
+#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1)
+
+struct ovs_nsh_key_base {
+ __u8 flags;
+ __u8 ttl;
+ __u8 mdtype;
+ __u8 np;
+ __be32 path_hdr;
+};
+
+#define NSH_MD1_CONTEXT_SIZE 4
+
+struct ovs_nsh_key_md1 {
+ __be32 context[NSH_MD1_CONTEXT_SIZE];
+};
+
/**
* enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
* @OVS_FLOW_ATTR_KEY: Nested %OVS_KEY_ATTR_* attributes specifying the flow
@@ -806,6 +830,8 @@ struct ovs_action_push_eth {
* packet.
* @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the
* packet.
+ * @OVS_ACTION_ATTR_PUSH_NSH: push NSH header to the packet.
+ * @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.
*
* Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
* fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -835,6 +861,8 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_TRUNC, /* u32 struct ovs_action_trunc. */
OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */
OVS_ACTION_ATTR_POP_ETH, /* No argument. */
+ OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */
+ OVS_ACTION_ATTR_POP_NSH, /* No argument. */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index 58fb827..ad689b5 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -14,6 +14,47 @@
#include <net/nsh.h>
#include <net/tun_proto.h>
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nsh_src, bool is_eth)
+{
+ struct nshhdr *nsh;
+ size_t length = nsh_hdr_len(nsh_src);
+ u8 next_proto;
+
+ if (is_eth) {
+ next_proto = TUN_P_ETHERNET;
+ } else {
+ next_proto = tun_p_from_eth_p(skb->protocol);
+ if (!next_proto)
+ return -ENOTSUPP;
+ }
+
+ /* Add the NSH header */
+ if (skb_cow_head(skb, length) < 0)
+ return -ENOMEM;
+
+ /* Add the NSH header */
+ if (skb_cow_head(skb, length) < 0)
+ return -ENOMEM;
+
+ if (!skb->inner_protocol) {
+ skb_set_inner_network_header(skb, skb->mac_len);
+ skb_set_inner_protocol(skb, skb->protocol);
+ }
+
+ skb_push(skb, length);
+ nsh = (struct nshhdr *)(skb->data);
+ memcpy(nsh, nsh_src, length);
+ nsh->np = next_proto;
+ nsh->mdtype &= NSH_MDTYPE_MASK;
+
+ skb->protocol = htons(ETH_P_NSH);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_push_nsh);
+
static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index a54a556..e969fad 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -38,11 +38,13 @@
#include <net/dsfield.h>
#include <net/mpls.h>
#include <net/sctp/checksum.h>
+#include <net/tun_proto.h>
#include "datapath.h"
#include "flow.h"
#include "conntrack.h"
#include "vport.h"
+#include "flow_netlink.h"
struct deferred_action {
struct sk_buff *skb;
@@ -380,6 +382,57 @@ static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
return 0;
}
+static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct nshhdr *nsh_src)
+{
+ bool is_eth = false;
+ int ret;
+
+ if (key->mac_proto == MAC_PROTO_ETHERNET)
+ is_eth = true;
+
+ ret = skb_push_nsh(skb, nsh_src, is_eth);
+ if (ret != 0)
+ return ret;
+
+ key->eth.type = htons(ETH_P_NSH);
+
+ /* safe right before invalidate_flow_key */
+ key->mac_proto = MAC_PROTO_NONE;
+ invalidate_flow_key(key);
+ return 0;
+}
+
+static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ struct nshhdr *nsh = (struct nshhdr *)(skb->data);
+ size_t length;
+ u16 inner_proto;
+
+ if (ovs_key_mac_proto(key) != MAC_PROTO_NONE ||
+ skb->protocol != htons(ETH_P_NSH)) {
+ return -EINVAL;
+ }
+
+ inner_proto = tun_p_to_eth_p(nsh->np);
+ if (!inner_proto)
+ return -ENOTSUPP;
+
+ length = nsh_hdr_len(nsh);
+ skb_pull(skb, length);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+ skb->protocol = inner_proto;
+
+ /* safe right before invalidate_flow_key */
+ if (inner_proto == htons(ETH_P_TEB))
+ key->mac_proto = MAC_PROTO_ETHERNET;
+ else
+ key->mac_proto = MAC_PROTO_NONE;
+ invalidate_flow_key(key);
+ return 0;
+}
+
static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
__be32 addr, __be32 new_addr)
{
@@ -602,6 +655,53 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key,
return 0;
}
+static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
+ const struct ovs_key_nsh *key,
+ const struct ovs_key_nsh *mask)
+{
+ struct nshhdr *nsh;
+ int err;
+ u8 flags;
+ u8 ttl;
+ int i;
+
+ err = skb_ensure_writable(skb, skb_network_offset(skb) +
+ sizeof(struct nshhdr));
+ if (unlikely(err))
+ return err;
+
+ nsh = (struct nshhdr *)skb_network_header(skb);
+
+ flags = nsh_get_flags(nsh);
+ flags = OVS_MASKED(flags, key->flags, mask->flags);
+ flow_key->nsh.flags = flags;
+ ttl = nsh_get_ttl(nsh);
+ ttl = OVS_MASKED(ttl, key->ttl, mask->ttl);
+ flow_key->nsh.ttl = ttl;
+ nsh_set_flags_and_ttl(nsh, flags, ttl);
+ nsh->path_hdr = OVS_MASKED(nsh->path_hdr, key->path_hdr,
+ mask->path_hdr);
+ flow_key->nsh.path_hdr = nsh->path_hdr;
+ switch (nsh->mdtype) {
+ case NSH_M_TYPE1:
+ for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++) {
+ nsh->md1.context[i] =
+ OVS_MASKED(nsh->md1.context[i], key->context[i],
+ mask->context[i]);
+ }
+ memcpy(flow_key->nsh.context, nsh->md1.context,
+ sizeof(nsh->md1.context));
+ break;
+ case NSH_M_TYPE2:
+ memset(flow_key->nsh.context, 0,
+ sizeof(flow_key->nsh.context));
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
/* Must follow skb_ensure_writable() since that can move the skb data. */
static void set_tp_port(struct sk_buff *skb, __be16 *port,
__be16 new_port, __sum16 *check)
@@ -1024,6 +1124,32 @@ static int execute_masked_set_action(struct sk_buff *skb,
get_mask(a, struct ovs_key_ethernet *));
break;
+ case OVS_KEY_ATTR_NSH: {
+ struct ovs_key_nsh nsh;
+ struct ovs_key_nsh nsh_mask;
+ size_t size = nla_len(a) / 2;
+ struct {
+ struct nlattr nla;
+ u8 data[size];
+ } attr, mask;
+
+ attr.nla.nla_type = nla_type(a);
+ attr.nla.nla_len = NLA_HDRLEN + size;
+ memcpy(attr.data, (char *)(a + 1), size);
+
+ mask.nla = attr.nla;
+ memcpy(mask.data, (char *)(a + 1) + size, size);
+
+ err = nsh_key_from_nlattr(&attr.nla, &nsh);
+ if (err)
+ break;
+ err = nsh_key_from_nlattr(&mask.nla, &nsh_mask);
+ if (err)
+ break;
+ err = set_nsh(skb, flow_key, &nsh, &nsh_mask);
+ break;
+ }
+
case OVS_KEY_ATTR_IPV4:
err = set_ipv4(skb, flow_key, nla_data(a),
get_mask(a, struct ovs_key_ipv4 *));
@@ -1210,6 +1336,21 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
case OVS_ACTION_ATTR_POP_ETH:
err = pop_eth(skb, key);
break;
+
+ case OVS_ACTION_ATTR_PUSH_NSH: {
+ u8 buffer[NSH_HDR_MAX_LEN];
+ struct nshhdr *nsh_hdr = (struct nshhdr *)buffer;
+ const struct nshhdr *nsh_src = nsh_hdr;
+
+ nsh_hdr_from_nlattr(nla_data(a), nsh_hdr,
+ NSH_HDR_MAX_LEN);
+ err = push_nsh(skb, key, nsh_src);
+ break;
+ }
+
+ case OVS_ACTION_ATTR_POP_NSH:
+ err = pop_nsh(skb, key);
+ break;
}
if (unlikely(err)) {
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 8c94cef..7a178d1 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -46,6 +46,7 @@
#include <net/ipv6.h>
#include <net/mpls.h>
#include <net/ndisc.h>
+#include <net/nsh.h>
#include "conntrack.h"
#include "datapath.h"
@@ -490,6 +491,56 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
return 0;
}
+static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ struct nshhdr *nsh;
+ unsigned int nh_ofs = skb_network_offset(skb);
+ u8 version, length;
+ int err;
+
+ err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN);
+ if (unlikely(err))
+ return err;
+
+ nsh = (struct nshhdr *)skb_network_header(skb);
+ version = nsh_get_ver(nsh);
+ length = nsh_hdr_len(nsh);
+
+ if (version != 0)
+ return -EINVAL;
+
+ err = check_header(skb, nh_ofs + length);
+ if (unlikely(err))
+ return err;
+
+ nsh = (struct nshhdr *)skb_network_header(skb);
+ key->nsh.flags = nsh_get_flags(nsh);
+ key->nsh.ttl = nsh_get_ttl(nsh);
+ key->nsh.mdtype = nsh->mdtype;
+ key->nsh.np = nsh->np;
+ key->nsh.path_hdr = nsh->path_hdr;
+ switch (key->nsh.mdtype) {
+ case NSH_M_TYPE1:
+ if (length != NSH_M_TYPE1_LEN)
+ return -EINVAL;
+ memcpy(key->nsh.context, nsh->md1.context,
+ sizeof(nsh->md1));
+ break;
+ case NSH_M_TYPE2:
+ /* Don't support MD type 2 metedata parsing yet */
+ if (length < NSH_BASE_HDR_LEN)
+ return -EINVAL;
+
+ memset(key->nsh.context, 0,
+ sizeof(nsh->md1));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* key_extract - extracts a flow key from an Ethernet frame.
* @skb: sk_buff that contains the frame, with skb->data pointing to the
@@ -735,6 +786,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
memset(&key->tp, 0, sizeof(key->tp));
}
}
+ } else if (key->eth.type == htons(ETH_P_NSH)) {
+ error = parse_nsh(skb, key);
+ if (error)
+ return error;
}
return 0;
}
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 1875bba..6a3cd9c 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -35,6 +35,7 @@
#include <net/inet_ecn.h>
#include <net/ip_tunnels.h>
#include <net/dst_metadata.h>
+#include <net/nsh.h>
struct sk_buff;
@@ -66,6 +67,15 @@ struct vlan_head {
(offsetof(struct sw_flow_key, recirc_id) + \
FIELD_SIZEOF(struct sw_flow_key, recirc_id))
+struct ovs_key_nsh {
+ u8 flags;
+ u8 ttl;
+ u8 mdtype;
+ u8 np;
+ __be32 path_hdr;
+ __be32 context[NSH_MD1_CONTEXT_SIZE];
+};
+
struct sw_flow_key {
u8 tun_opts[IP_TUNNEL_OPTS_MAX];
u8 tun_opts_len;
@@ -144,6 +154,7 @@ struct sw_flow_key {
};
} ipv6;
};
+ struct ovs_key_nsh nsh; /* network service header */
struct {
/* Connection tracking fields not packed above. */
struct {
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index e8eb427..17df00a 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -48,6 +48,7 @@
#include <net/ndisc.h>
#include <net/mpls.h>
#include <net/vxlan.h>
+#include <net/tun_proto.h>
#include "flow_netlink.h"
@@ -78,9 +79,11 @@ static bool actions_may_change_flow(const struct nlattr *actions)
case OVS_ACTION_ATTR_HASH:
case OVS_ACTION_ATTR_POP_ETH:
case OVS_ACTION_ATTR_POP_MPLS:
+ case OVS_ACTION_ATTR_POP_NSH:
case OVS_ACTION_ATTR_POP_VLAN:
case OVS_ACTION_ATTR_PUSH_ETH:
case OVS_ACTION_ATTR_PUSH_MPLS:
+ case OVS_ACTION_ATTR_PUSH_NSH:
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_SAMPLE:
case OVS_ACTION_ATTR_SET:
@@ -322,12 +325,27 @@ size_t ovs_tun_key_attr_size(void)
+ nla_total_size(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
}
+size_t ovs_nsh_key_attr_size(void)
+{
+ /* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider
+ * updating this function.
+ */
+ return nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */
+ /* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are
+ * mutually exclusive, so the bigger one can cover
+ * the small one.
+ *
+ * OVS_NSH_KEY_ATTR_MD2
+ */
+ + nla_total_size(NSH_CTX_HDRS_MAX_LEN);
+}
+
size_t ovs_key_attr_size(void)
{
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
* updating this function.
*/
- BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 28);
+ BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 29);
return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
@@ -341,6 +359,8 @@ size_t ovs_key_attr_size(void)
+ nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
+ nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
+ nla_total_size(40) /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
+ + nla_total_size(0) /* OVS_KEY_ATTR_NSH */
+ + ovs_nsh_key_attr_size()
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
@@ -373,6 +393,13 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) },
};
+static const struct ovs_len_tbl
+ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
+ [OVS_NSH_KEY_ATTR_BASE] = { .len = 8 },
+ [OVS_NSH_KEY_ATTR_MD1] = { .len = 16 },
+ [OVS_NSH_KEY_ATTR_MD2] = { .len = OVS_ATTR_VARIABLE },
+};
+
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ENCAP] = { .len = OVS_ATTR_NESTED },
@@ -405,6 +432,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
.len = sizeof(struct ovs_key_ct_tuple_ipv4) },
[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {
.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
+ [OVS_KEY_ATTR_NSH] = { .len = OVS_ATTR_NESTED,
+ .next = ovs_nsh_key_attr_lens, },
};
static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -1179,6 +1208,304 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
return 0;
}
+int nsh_hdr_from_nlattr(const struct nlattr *attr,
+ struct nshhdr *nsh, size_t size)
+{
+ struct nlattr *a;
+ int rem;
+ u8 flags = 0;
+ u8 ttl = 0;
+ int mdlen = 0;
+ bool has_md1 = false;
+ bool has_md2 = false;
+ u8 len;
+
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+
+ if (type > OVS_NSH_KEY_ATTR_MAX) {
+ OVS_NLERR(1, "nsh attr %d is out of range max %d",
+ type, OVS_NSH_KEY_ATTR_MAX);
+ return -EINVAL;
+ }
+
+ if (!check_attr_len(nla_len(a),
+ ovs_nsh_key_attr_lens[type].len)) {
+ OVS_NLERR(
+ 1,
+ "nsh attr %d has unexpected len %d expected %d",
+ type,
+ nla_len(a),
+ ovs_nsh_key_attr_lens[type].len
+ );
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+ flags = base->flags;
+ ttl = base->ttl;
+ nsh->np = base->np;
+ nsh->mdtype = base->mdtype;
+ nsh->path_hdr = base->path_hdr;
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+ struct nsh_md1_ctx *md1_dst = &nsh->md1;
+
+ has_md1 = true;
+ mdlen = nla_len(a);
+ if (((mdlen + NSH_BASE_HDR_LEN) != NSH_M_TYPE1_LEN) ||
+ ((mdlen + NSH_BASE_HDR_LEN) > size) ||
+ (mdlen <= 0)) {
+ OVS_NLERR(
+ 1,
+ "length %d of nsh attr %d is invalid",
+ mdlen,
+ type
+ );
+ return -EINVAL;
+ }
+ memcpy(md1_dst, md1, mdlen);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2: {
+ const struct u8 *md2 = nla_data(a);
+ struct nsh_md2_tlv *md2_dst = &nsh->md2;
+
+ has_md2 = true;
+ mdlen = nla_len(a);
+ if (((mdlen + NSH_BASE_HDR_LEN) > size) ||
+ (mdlen <= 0)) {
+ OVS_NLERR(
+ 1,
+ "length %d of nsh attr %d is invalid",
+ mdlen,
+ type
+ );
+ return -EINVAL;
+ }
+ memcpy(md2_dst, md2, mdlen);
+ break;
+ }
+ default:
+ OVS_NLERR(1, "Unknown nsh attribute %d",
+ type);
+ return -EINVAL;
+ }
+ }
+
+ if (rem > 0) {
+ OVS_NLERR(1, "nsh attribute has %d unknown bytes.", rem);
+ return -EINVAL;
+ }
+
+ if ((has_md1 && nsh->mdtype != NSH_M_TYPE1) ||
+ (has_md2 && nsh->mdtype != NSH_M_TYPE2)) {
+ OVS_NLERR(1,
+ "nsh attribute has unmatched MD type %d.",
+ nsh->mdtype);
+ return -EINVAL;
+ }
+
+ if (unlikely(has_md1 && has_md2)) {
+ OVS_NLERR(1, "both nsh md1 and md2 attribute are there");
+ return -EINVAL;
+ }
+
+ if (unlikely(!has_md1 && !has_md2)) {
+ OVS_NLERR(1, "neither nsh md1 nor md2 attribute is there");
+ return -EINVAL;
+ }
+
+ /* nsh header length = NSH_BASE_HDR_LEN + mdlen */
+ nsh->ver_flags_ttl_len = 0;
+ len = NSH_BASE_HDR_LEN + mdlen;
+ nsh_set_flags_ttl_len(nsh, flags, ttl, len);
+
+ return 0;
+}
+
+int nsh_key_from_nlattr(const struct nlattr *attr,
+ struct ovs_key_nsh *nsh)
+{
+ struct nlattr *a;
+ int rem;
+ bool has_md1 = false;
+
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+
+ if (type > OVS_NSH_KEY_ATTR_MAX) {
+ OVS_NLERR(1, "nsh attr %d is out of range max %d",
+ type, OVS_NSH_KEY_ATTR_MAX);
+ return -EINVAL;
+ }
+
+ if (!check_attr_len(nla_len(a),
+ ovs_nsh_key_attr_lens[type].len)) {
+ OVS_NLERR(
+ 1,
+ "nsh attr %d has unexpected len %d expected %d",
+ type,
+ nla_len(a),
+ ovs_nsh_key_attr_lens[type].len
+ );
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+
+ memcpy(nsh, base, sizeof(*base));
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+
+ has_md1 = true;
+ memcpy(nsh->context, md1->context, sizeof(*md1));
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2:
+ /* Not supported yet */
+ return -ENOTSUPP;
+ default:
+ OVS_NLERR(1, "Unknown nsh attribute %d",
+ type);
+ return -EINVAL;
+ }
+ }
+
+ if (rem > 0) {
+ OVS_NLERR(1, "nsh attribute has %d unknown bytes.", rem);
+ return -EINVAL;
+ }
+
+ if ((has_md1 && nsh->mdtype != NSH_M_TYPE1)) {
+ OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
+ nsh->mdtype);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nsh_key_put_from_nlattr(const struct nlattr *attr,
+ struct sw_flow_match *match, bool is_mask,
+ bool is_push_nsh, bool log)
+{
+ struct nlattr *a;
+ int rem;
+ bool has_md1 = false;
+ bool has_md2 = false;
+ u8 mdtype = 0;
+ int mdlen = 0;
+
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+ int i;
+
+ if (type > OVS_NSH_KEY_ATTR_MAX) {
+ OVS_NLERR(log, "nsh attr %d is out of range max %d",
+ type, OVS_NSH_KEY_ATTR_MAX);
+ return -EINVAL;
+ }
+
+ if (!check_attr_len(nla_len(a),
+ ovs_nsh_key_attr_lens[type].len)) {
+ OVS_NLERR(
+ log,
+ "nsh attr %d has unexpected len %d expected %d",
+ type,
+ nla_len(a),
+ ovs_nsh_key_attr_lens[type].len
+ );
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+
+ mdtype = base->mdtype;
+ SW_FLOW_KEY_PUT(match, nsh.flags,
+ base->flags, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.ttl,
+ base->ttl, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.mdtype,
+ base->mdtype, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.np,
+ base->np, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.path_hdr,
+ base->path_hdr, is_mask);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+
+ has_md1 = true;
+ for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
+ SW_FLOW_KEY_PUT(match, nsh.context[i],
+ md1->context[i], is_mask);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2:
+ if (!is_push_nsh) /* Not supported MD type 2 yet */
+ return -ENOTSUPP;
+
+ has_md2 = true;
+ mdlen = nla_len(a);
+ if ((mdlen > NSH_CTX_HDRS_MAX_LEN) ||
+ (mdlen <= 0))
+ return -EINVAL;
+ break;
+ default:
+ OVS_NLERR(log, "Unknown nsh attribute %d",
+ type);
+ return -EINVAL;
+ }
+ }
+
+ if (rem > 0) {
+ OVS_NLERR(log, "nsh attribute has %d unknown bytes.", rem);
+ return -EINVAL;
+ }
+
+ if (!is_mask) {
+ if ((has_md1 && mdtype != NSH_M_TYPE1)) {
+ OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
+ mdtype);
+ return -EINVAL;
+ }
+ }
+
+ if (is_push_nsh & !is_mask) {
+ if ((has_md1 && mdtype != NSH_M_TYPE1) ||
+ (has_md2 && mdtype != NSH_M_TYPE2) ||
+ (has_md1 && has_md2) ||
+ (!has_md1 && !has_md2)) {
+ OVS_NLERR(
+ 1,
+ "push nsh attributes are invalid for type %d.",
+ mdtype
+ );
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
u64 attrs, const struct nlattr **a,
bool is_mask, bool log)
@@ -1306,6 +1633,13 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
attrs &= ~(1 << OVS_KEY_ATTR_ARP);
}
+ if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
+ if (nsh_key_put_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
+ is_mask, false, log) < 0)
+ return -EINVAL;
+ attrs &= ~(1 << OVS_KEY_ATTR_NSH);
+ }
+
if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
const struct ovs_key_mpls *mpls_key;
@@ -1622,6 +1956,40 @@ static int ovs_nla_put_vlan(struct sk_buff *skb, const struct vlan_head *vh,
return 0;
}
+static int nsh_key_to_nlattr(const struct ovs_key_nsh *nsh, bool is_mask,
+ struct sk_buff *skb)
+{
+ struct nlattr *start;
+ struct ovs_nsh_key_base base;
+ struct ovs_nsh_key_md1 md1;
+
+ memcpy(&base, nsh, sizeof(base));
+
+ if (is_mask || nsh->mdtype == NSH_M_TYPE1)
+ memcpy(md1.context, nsh->context, sizeof(md1));
+
+ start = nla_nest_start(skb, OVS_KEY_ATTR_NSH);
+ if (!start)
+ return -EMSGSIZE;
+
+ if (nla_put(skb, OVS_NSH_KEY_ATTR_BASE, sizeof(base), &base))
+ goto nla_put_failure;
+
+ if (is_mask || nsh->mdtype == NSH_M_TYPE1) {
+ if (nla_put(skb, OVS_NSH_KEY_ATTR_MD1, sizeof(md1), &md1))
+ goto nla_put_failure;
+ }
+
+ /* Don't support MD type 2 yet */
+
+ nla_nest_end(skb, start);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
const struct sw_flow_key *output, bool is_mask,
struct sk_buff *skb)
@@ -1750,6 +2118,9 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
ipv6_key->ipv6_tclass = output->ip.tos;
ipv6_key->ipv6_hlimit = output->ip.ttl;
ipv6_key->ipv6_frag = output->ip.frag;
+ } else if (swkey->eth.type == htons(ETH_P_NSH)) {
+ if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
+ goto nla_put_failure;
} else if (swkey->eth.type == htons(ETH_P_ARP) ||
swkey->eth.type == htons(ETH_P_RARP)) {
struct ovs_key_arp *arp_key;
@@ -2242,6 +2613,19 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
return err;
}
+static bool validate_nsh(const struct nlattr *attr, bool is_mask,
+ bool is_push_nsh, bool log)
+{
+ struct sw_flow_match match;
+ struct sw_flow_key key;
+ int ret = 0;
+
+ ovs_match_init(&match, &key, true, NULL);
+ ret = nsh_key_put_from_nlattr(attr, &match, is_mask,
+ is_push_nsh, log);
+ return ((ret != 0) ? false : true);
+}
+
/* Return false if there are any non-masked bits set.
* Mask follows data immediately, before any netlink padding.
*/
@@ -2384,6 +2768,11 @@ static int validate_set(const struct nlattr *a,
break;
+ case OVS_KEY_ATTR_NSH:
+ if (!validate_nsh(nla_data(a), masked, false, log))
+ return -EINVAL;
+ break;
+
default:
return -EINVAL;
}
@@ -2482,6 +2871,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
[OVS_ACTION_ATTR_POP_ETH] = 0,
+ [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
+ [OVS_ACTION_ATTR_POP_NSH] = 0,
};
const struct ovs_action_push_vlan *vlan;
int type = nla_type(a);
@@ -2636,6 +3027,19 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
mac_proto = MAC_PROTO_ETHERNET;
break;
+ case OVS_ACTION_ATTR_PUSH_NSH:
+ mac_proto = MAC_PROTO_NONE;
+ if (!validate_nsh(nla_data(a), false, true, true))
+ return -EINVAL;
+ break;
+
+ case OVS_ACTION_ATTR_POP_NSH:
+ if (key->nsh.np == TUN_P_ETHERNET)
+ mac_proto = MAC_PROTO_ETHERNET;
+ else
+ mac_proto = MAC_PROTO_NONE;
+ break;
+
default:
OVS_NLERR(log, "Unknown Action type %d", type);
return -EINVAL;
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 929c665..7be6750 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -79,4 +79,8 @@ int ovs_nla_put_actions(const struct nlattr *attr,
void ovs_nla_free_flow_actions(struct sw_flow_actions *);
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *);
+int nsh_key_from_nlattr(const struct nlattr *attr, struct ovs_key_nsh *nsh);
+int nsh_hdr_from_nlattr(const struct nlattr *attr, struct nshhdr *nsh_src,
+ size_t size);
+
#endif /* flow_netlink.h */
--
2.5.5
^ permalink raw reply related
* Re: Question about ip_defrag
From: Jesper Dangaard Brouer @ 2017-08-30 12:22 UTC (permalink / raw)
To: Florian Westphal
Cc: liujian (CE), davem@davemloft.net, edumazet@google.com,
netdev@vger.kernel.org, Wangkefeng (Kevin), weiyongjun (A),
brouer
In-Reply-To: <20170830115820.GC9993@breakpoint.cc>
On Wed, 30 Aug 2017 13:58:20 +0200
Florian Westphal <fw@strlen.de> wrote:
> Jesper Dangaard Brouer <brouer@redhat.com> wrote:
> > > I take 2) back. Its wrong to do this, for large NR_CPU values it
> > > would even overflow.
> >
> > Alternatively solution 3:
> > Why do we want to maintain a (4MBytes) memory limit, across all CPUs?
> > Couldn't we just allow each CPU to have a memory limit?
>
> Consider ipv4, ipv6, nf ipv6 defrag, 6lowpan, and 8k cpus... This will
> render any limit useless.
With 8K CPUs I agree, that this might be a bad idea!
> > > > To me it looks like we/I have been using the wrong API for comparing
> > > > against percpu_counters. I guess we should have used __percpu_counter_compare().
> > >
> > > Are you sure? For liujian use case (64 cores) it looks like we would
> > > always fall through to percpu_counter_sum() so we eat spinlock_irqsave
> > > cost for all compares.
> > >
> > > Before we entertain this we should consider reducing frag_percpu_counter_batch
> > > to a smaller value.
> >
> > Yes, I agree, we really need to lower/reduce the frag_percpu_counter_batch.
> > As you say, else the __percpu_counter_compare() call will be useless
> > (around systems with >= 32 CPUs).
> >
> > I think the bug is in frag_mem_limit(). It just reads the global
> > counter (fbc->count), without considering other CPUs can have upto 130K
> > that haven't been subtracted yet (due to 3M low limit, become dangerous
> > at >=24 CPUs). The __percpu_counter_compare() does the right thing,
> > and takes into account the number of (online) CPUs and batch size, to
> > account for this.
>
> Right, I think we should at very least use __percpu_counter_compare
> before denying a new frag queue allocation request.
>
> I'll create a patch.
Oh, I've already started working on a patch, that I'm testing now. But
if you want to take the assignment then I'm fine with that!. I just
though that it was my responsibility to fix, given I introduced
percpu_counter usage (back in 2013-01-28 / 6d7b857d541e).
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH net 0/9] net/sched: init failure fixes
From: Jamal Hadi Salim @ 2017-08-30 12:15 UTC (permalink / raw)
To: Nikolay Aleksandrov, netdev
Cc: edumazet, xiyou.wangcong, jiri, roopa, Lucas Bates
In-Reply-To: <1504086545-7777-1-git-send-email-nikolay@cumulusnetworks.com>
On 17-08-30 05:48 AM, Nikolay Aleksandrov wrote:
> Hi all,
> I went over all qdiscs' init, destroy and reset callbacks and found the
> issues fixed in each patch. Mostly they are null pointer dereferences due
> to uninitialized timer (qdisc watchdog) or double frees due to ->destroy
> cleaning up a second time. There's more information in each patch.
> I've tested these by either sending wrong attributes from user-spaces, no
> attributes or by simulating memory alloc failure where applicable. Also
> tried all of the qdiscs as a default qdisc.
>
> Most of these bugs were present before commit 87b60cfacf9f, I've tried to
> include proper fixes tags in each patch.
>
> I haven't included individual patch acks in the set, I'd appreciate it if
> you take another look and resend them.
>
Hi Nik,
For all patches:
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Would you please consider adding all the the tests
you used to create the oopses in selftests? It will ensure this
embarassing bugs get caught should they ever happen again.
If you need help ping Lucas on Cc.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH v2 2/3] dt-binding: net: sfp binding documentation
From: Sergei Shtylyov @ 2017-08-30 12:13 UTC (permalink / raw)
To: Baruch Siach
Cc: Rob Herring, Mark Rutland, Andrew Lunn, Florian Fainelli,
David S. Miller, Russell King, netdev, devicetree
In-Reply-To: <20170830112557.dhcl3pv7gmuzg22v@tarshish>
On 08/30/2017 02:25 PM, Baruch Siach wrote:
>>>>> Add device-tree binding documentation SFP transceivers. Support for SFP
>>>>> transceivers has been recently introduced (drivers/net/phy/sfp.c).
>>>>>
>>>>> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
>>>>> ---
>>>>> v2:
>>>>> Rename -gpio properties to -gpios
>>>>> Rename the rate-select-gpio property to rate-select0-gpios
>>>>> Add the rate-select1-gpios property
>>>>> Add examples
>>>>> ---
>>>>> Documentation/devicetree/bindings/net/sff,sfp.txt | 74 +++++++++++++++++++++++
>>>>> 1 file changed, 74 insertions(+)
>>>>> create mode 100644 Documentation/devicetree/bindings/net/sff,sfp.txt
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
>>>>> new file mode 100644
>>>>> index 000000000000..1d9c786d6287
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/net/sff,sfp.txt
>>>>> @@ -0,0 +1,74 @@
>>>>> +Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
>>>>> +Transceiver
>>>>> +
>>>>> +Required properties:
>>>>> +
>>>>> +- compatible : must be "sff,sfp"
>>>>> +
>>>>> +Optional Properties:
>>>>> +
>>>>> +- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
>>>>> + interface
>>>>> +
>>>>> +- moddef0-gpios : phandle of the MOD-DEF0 (AKA Mod_ABS) module presence input
>>>>> + gpio signal
>>>>
>>>> Your example shows there's GPIO phandle *and* specifier.
>>>
>>> Would "GPIO specifier" be enough here?
>>
>> No, specifier is the cells following GPIO (or any other) phandle.
>
> So this should be "GPIO phandle and specifier of ...", is that correct?
Exactly. The length of the GPIO specifier is determined by the
"#gpio-cells" prop of the GPIO node your phandle refers to.
> I have found very few (< 4) occurrences of this language in (lots of) '-gpios'
> property descriptions under Documentation/devicetree/bindings/.
You better see Documentation/devicetree/bindings/gpio/gpio.txt.
> Is this a new
> requirement?
Not at all, and it's not limited to GPIOs. Nobody reads the specs. :-)
> baruch
MBR, Sergei
^ permalink raw reply
* Re: [patch net-next v2 3/3] net/sched: Change act_api and act_xxx modules to use IDR
From: Jamal Hadi Salim @ 2017-08-30 12:11 UTC (permalink / raw)
To: Chris Mi, netdev; +Cc: xiyou.wangcong, jiri, davem, mawilcox
In-Reply-To: <1504074719-15147-4-git-send-email-chrism@mellanox.com>
On 17-08-30 02:31 AM, Chris Mi wrote:
> Typically, each TC filter has its own action. All the actions of the
> same type are saved in its hash table. But the hash buckets are too
> small that it degrades to a list. And the performance is greatly
> affected. For example, it takes about 0m11.914s to insert 64K rules.
> If we convert the hash table to IDR, it only takes about 0m1.500s.
> The improvement is huge.
>
> But please note that the test result is based on previous patch that
> cls_flower uses IDR.
>
> Signed-off-by: Chris Mi <chrism@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Also already acked this before but you left it out in this
version. If you make changes to the patch then you will need
a new ACK.
Dont forget to update selftests please.
cheers,
jamal
^ permalink raw reply
* Re: [patch net-next v2 2/3] net/sched: Change cls_flower to use IDR
From: Jamal Hadi Salim @ 2017-08-30 12:09 UTC (permalink / raw)
To: Chris Mi, netdev; +Cc: xiyou.wangcong, jiri, davem, mawilcox
In-Reply-To: <1504074719-15147-3-git-send-email-chrism@mellanox.com>
On 17-08-30 02:31 AM, Chris Mi wrote:
> Currently, all filters with the same priority are linked in a doubly
> linked list. Every filter should have a unique handle. To make the
> handle unique, we need to iterate the list every time to see if the
> handle exists or not when inserting a new filter. It is time-consuming.
> For example, it takes about 5m3.169s to insert 64K rules.
>
> This patch changes cls_flower to use IDR. With this patch, it
> takes about 0m1.127s to insert 64K rules. The improvement is huge.
>
> But please note that in this testing, all filters share the same action.
> If every filter has a unique action, that is another bottleneck.
> Follow-up patch in this patchset addresses that.
>
> Signed-off-by: Chris Mi <chrism@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
BTW: I'd already acked this before but you left it out in this
version.
cheers,
jamal
^ permalink raw reply
* [patch net-next 8/8] mlxsw: spectrum_dpipe: Add support for controlling IPv6 neighbor counters
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add support for controlling IPv6 neighbor counters via dpipe.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 75da2ef..51e6846 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -679,8 +679,15 @@ mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp *mlxsw_sp,
if (!rif)
continue;
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
+ int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
+
+ if (neigh_type != type)
+ continue;
+
+ if (neigh_type == AF_INET6 &&
+ mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
continue;
+
mlxsw_sp_neigh_entry_counter_update(mlxsw_sp,
neigh_entry,
enable);
@@ -778,6 +785,14 @@ mlxsw_sp_dpipe_table_host6_entries_dump(void *priv, bool counters_enabled,
dump_ctx, AF_INET6);
}
+static int mlxsw_sp_dpipe_table_host6_counters_update(void *priv, bool enable)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET6);
+ return 0;
+}
+
static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
{
struct mlxsw_sp *mlxsw_sp = priv;
@@ -789,6 +804,7 @@ static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
.matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
.actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
.entries_dump = mlxsw_sp_dpipe_table_host6_entries_dump,
+ .counters_set_update = mlxsw_sp_dpipe_table_host6_counters_update,
.size_get = mlxsw_sp_dpipe_table_host6_size_get,
};
--
2.9.3
^ permalink raw reply related
* [patch net-next 7/8] mlxsw: spectrum_router: Add support for setting counters on IPv6 neighbors
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add support for setting counters on IPv6 neighbors based on dpipe's host6
table counter status.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index db57c0c..0cf6810 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -1008,21 +1008,33 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
}
static bool
-mlxsw_sp_neigh4_counter_should_alloc(struct mlxsw_sp *mlxsw_sp)
+mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_neigh_entry *neigh_entry)
{
struct devlink *devlink;
+ const char *table_name;
+
+ switch (mlxsw_sp_neigh_entry_type(neigh_entry)) {
+ case AF_INET:
+ table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4;
+ break;
+ case AF_INET6:
+ table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6;
+ break;
+ default:
+ WARN_ON(1);
+ return false;
+ }
devlink = priv_to_devlink(mlxsw_sp->core);
- return devlink_dpipe_table_counter_enabled(devlink,
- MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
+ return devlink_dpipe_table_counter_enabled(devlink, table_name);
}
static void
mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry)
{
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != AF_INET ||
- !mlxsw_sp_neigh4_counter_should_alloc(mlxsw_sp))
+ if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry))
return;
if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
--
2.9.3
^ permalink raw reply related
* [patch net-next 6/8] mlxsw: spectrum_dpipe: Add support for IPv6 host table dump
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add support for IPv6 host table dump.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 75 ++++++++++++++++++++--
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 5924e97..75da2ef 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -386,8 +386,19 @@ mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match *match
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
- match->header = &devlink_dpipe_header_ipv4;
- match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ switch (type) {
+ case AF_INET:
+ match->header = &devlink_dpipe_header_ipv4;
+ match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ break;
+ case AF_INET6:
+ match->header = &devlink_dpipe_header_ipv6;
+ match->field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
action->header = &devlink_dpipe_header_ethernet;
@@ -424,7 +435,18 @@ mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
match_value->match = match;
- match_value->value_size = sizeof(u32);
+ switch (type) {
+ case AF_INET:
+ match_value->value_size = sizeof(u32);
+ break;
+ case AF_INET6:
+ match_value->value_size = sizeof(struct in6_addr);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
if (!match_value->value)
return -ENOMEM;
@@ -479,6 +501,20 @@ mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
}
static void
+mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry *entry,
+ struct mlxsw_sp_neigh_entry *neigh_entry,
+ struct mlxsw_sp_rif *rif)
+{
+ struct in6_addr *dip;
+ unsigned char *ha;
+
+ ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
+ dip = mlxsw_sp_neigh6_entry_dip(neigh_entry);
+
+ __mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, dip);
+}
+
+static void
mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
struct devlink_dpipe_entry *entry,
struct mlxsw_sp_neigh_entry *neigh_entry,
@@ -487,7 +523,18 @@ mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
{
int err;
- mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
+ switch (type) {
+ case AF_INET:
+ mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
+ break;
+ case AF_INET6:
+ mlxsw_sp_dpipe_table_host6_entry_fill(entry, neigh_entry, rif);
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
err = mlxsw_sp_neigh_counter_get(mlxsw_sp, neigh_entry,
&entry->counter);
if (!err)
@@ -526,7 +573,13 @@ mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp *mlxsw_sp,
rif_neigh_count = 0;
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
+ int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
+
+ if (neigh_type != type)
+ continue;
+
+ if (neigh_type == AF_INET6 &&
+ mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
continue;
if (rif_neigh_count < rif_neigh_skip)
@@ -714,6 +767,17 @@ mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)
return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);
}
+static int
+mlxsw_sp_dpipe_table_host6_entries_dump(void *priv, bool counters_enabled,
+ struct devlink_dpipe_dump_ctx *dump_ctx)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,
+ counters_enabled,
+ dump_ctx, AF_INET6);
+}
+
static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
{
struct mlxsw_sp *mlxsw_sp = priv;
@@ -724,6 +788,7 @@ static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
.matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
.actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
+ .entries_dump = mlxsw_sp_dpipe_table_host6_entries_dump,
.size_get = mlxsw_sp_dpipe_table_host6_size_get,
};
--
2.9.3
^ permalink raw reply related
* [patch net-next 5/8] mlxsw: spectrum_dpipe: Make host entry fill handler more generic
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Change the host entry filler helper to be applicable for both IPv4/6
addresses.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 93ba6a6..5924e97 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -439,13 +439,12 @@ mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
}
static void
-__mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
- struct mlxsw_sp_rif *rif,
- unsigned char *ha, u32 dip)
+__mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry *entry,
+ struct mlxsw_sp_rif *rif,
+ unsigned char *ha, void *dip)
{
struct devlink_dpipe_value *value;
u32 *rif_value;
- u32 *dip_value;
u8 *ha_value;
/* Set Match RIF index */
@@ -458,9 +457,7 @@ __mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
/* Set Match DIP */
value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
-
- dip_value = value->value;
- *dip_value = dip;
+ memcpy(value->value, dip, value->value_size);
/* Set Action DMAC */
value = entry->action_values;
@@ -478,7 +475,7 @@ mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
dip = mlxsw_sp_neigh4_entry_dip(neigh_entry);
- __mlxsw_sp_dpipe_table_host4_entry_fill(entry, rif, ha, dip);
+ __mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, &dip);
}
static void
--
2.9.3
^ permalink raw reply related
* [patch net-next 4/8] mlxsw: spectrum_router: Add IPv6 neighbor access helper
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add helper for accessing destination IP in case of IPv6 neighbor.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 9 +++++++++
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 2 ++
2 files changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 1f41bcd..db57c0c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -947,6 +947,15 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
return ntohl(*((__be32 *) n->primary_key));
}
+struct in6_addr *
+mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
+{
+ struct neighbour *n;
+
+ n = neigh_entry->key.n;
+ return (struct in6_addr *) &n->primary_key;
+}
+
int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
u64 *p_counter)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 5b68616..87a04af 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -65,6 +65,8 @@ int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry);
unsigned char *
mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry);
u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
+struct in6_addr *
+mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
#define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \
for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); neigh_entry; \
--
2.9.3
^ permalink raw reply related
* [patch net-next 3/8] mlxsw: spectrum_dpipe: Add IPv6 host table initial support
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add IPv6 host table initial support. The action behavior for both IPv4/6
tables is the same, thus the same action dump op is used. Neighbors with
link local address are ignored.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 76 ++++++++++++++++++++--
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.h | 1 +
2 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 3ea1314..93ba6a6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -76,6 +76,7 @@ static struct devlink_dpipe_header *mlxsw_dpipe_headers[] = {
&mlxsw_sp_dpipe_header_metadata,
&devlink_dpipe_header_ethernet,
&devlink_dpipe_header_ipv4,
+ &devlink_dpipe_header_ipv6,
};
static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers = {
@@ -328,9 +329,21 @@ static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff *skb, int type)
if (err)
return err;
- match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
- match.header = &devlink_dpipe_header_ipv4;
- match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ switch (type) {
+ case AF_INET:
+ match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
+ match.header = &devlink_dpipe_header_ipv4;
+ match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ break;
+ case AF_INET6:
+ match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
+ match.header = &devlink_dpipe_header_ipv6;
+ match.field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
return devlink_dpipe_match_put(skb, &match);
}
@@ -342,7 +355,7 @@ mlxsw_sp_dpipe_table_host4_matches_dump(void *priv, struct sk_buff *skb)
}
static int
-mlxsw_sp_dpipe_table_host4_actions_dump(void *priv, struct sk_buff *skb)
+mlxsw_sp_dpipe_table_host_actions_dump(void *priv, struct sk_buff *skb)
{
struct devlink_dpipe_action action = {0};
@@ -648,8 +661,15 @@ mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp *mlxsw_sp, int type)
if (!rif)
continue;
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
+ int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
+
+ if (neigh_type != type)
continue;
+
+ if (neigh_type == AF_INET6 &&
+ mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
+ continue;
+
size++;
}
}
@@ -667,7 +687,7 @@ static u64 mlxsw_sp_dpipe_table_host4_size_get(void *priv)
static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops = {
.matches_dump = mlxsw_sp_dpipe_table_host4_matches_dump,
- .actions_dump = mlxsw_sp_dpipe_table_host4_actions_dump,
+ .actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
.entries_dump = mlxsw_sp_dpipe_table_host4_entries_dump,
.counters_set_update = mlxsw_sp_dpipe_table_host4_counters_update,
.size_get = mlxsw_sp_dpipe_table_host4_size_get,
@@ -691,6 +711,43 @@ static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp *mlxsw_sp)
MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
}
+static int
+mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)
+{
+ return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);
+}
+
+static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET6);
+}
+
+static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
+ .matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
+ .actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
+ .size_get = mlxsw_sp_dpipe_table_host6_size_get,
+};
+
+static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp *mlxsw_sp)
+{
+ struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+
+ return devlink_dpipe_table_register(devlink,
+ MLXSW_SP_DPIPE_TABLE_NAME_HOST6,
+ &mlxsw_sp_host6_ops,
+ mlxsw_sp, false);
+}
+
+static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+
+ devlink_dpipe_table_unregister(devlink,
+ MLXSW_SP_DPIPE_TABLE_NAME_HOST6);
+}
+
int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
@@ -707,8 +764,14 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
err = mlxsw_sp_dpipe_host4_table_init(mlxsw_sp);
if (err)
goto err_host4_table_init;
+
+ err = mlxsw_sp_dpipe_host6_table_init(mlxsw_sp);
+ if (err)
+ goto err_host6_table_init;
return 0;
+err_host6_table_init:
+ mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
err_host4_table_init:
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
err_erif_table_init:
@@ -720,6 +783,7 @@ void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+ mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);
mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
devlink_dpipe_headers_unregister(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
index c56a3d9..283fde4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
@@ -55,5 +55,6 @@ static inline void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
#define MLXSW_SP_DPIPE_TABLE_NAME_ERIF "mlxsw_erif"
#define MLXSW_SP_DPIPE_TABLE_NAME_HOST4 "mlxsw_host4"
+#define MLXSW_SP_DPIPE_TABLE_NAME_HOST6 "mlxsw_host6"
#endif /* _MLXSW_PIPELINE_H_*/
--
2.9.3
^ permalink raw reply related
* [patch net-next 2/8] mlxsw: spectrum_router: Export IPv6 link local address check helper
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Neighbors with link local addresses are not offloaded to the host table,
yet, the are maintained in the driver for adjacency table usage. When
dumping the IPv6 host neighbors this link local neighbors should be
ignored. This patch exports this helper for dpipe usage.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 6 ++++--
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 377d85c..1f41bcd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -1396,8 +1396,10 @@ mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
}
-static bool mlxsw_sp_neigh_ipv6_ignore(struct neighbour *n)
+bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
{
+ struct neighbour *n = neigh_entry->key.n;
+
/* Packets with a link-local destination address are trapped
* after LPM lookup and never reach the neighbour table, so
* there is no need to program such neighbours to the device.
@@ -1420,7 +1422,7 @@ mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
mlxsw_sp_rauht_op(adding));
} else if (neigh_entry->key.n->tbl->family == AF_INET6) {
- if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry->key.n))
+ if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
return;
mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
mlxsw_sp_rauht_op(adding));
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index fb0f971..5b68616 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -76,5 +76,6 @@ void
mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
bool adding);
+bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry);
#endif /* _MLXSW_ROUTER_H_*/
--
2.9.3
^ permalink raw reply related
* [patch net-next 1/8] devlink: Add IPv6 header for dpipe
From: Jiri Pirko @ 2017-08-30 12:02 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
This will be used by the IPv6 host table which will be introduced in the
following patches. The fields in the header are added per-use. This header
is global and can be reused by many drivers.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/devlink.h | 1 +
include/uapi/linux/devlink.h | 5 +++++
net/core/devlink.c | 17 +++++++++++++++++
3 files changed, 23 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index aaf7178..b9654e1 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -330,6 +330,7 @@ int devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match);
extern struct devlink_dpipe_header devlink_dpipe_header_ethernet;
extern struct devlink_dpipe_header devlink_dpipe_header_ipv4;
+extern struct devlink_dpipe_header devlink_dpipe_header_ipv6;
#else
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 6c17254..0cbca96 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -234,9 +234,14 @@ enum devlink_dpipe_field_ipv4_id {
DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
};
+enum devlink_dpipe_field_ipv6_id {
+ DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
+};
+
enum devlink_dpipe_header_id {
DEVLINK_DPIPE_HEADER_ETHERNET,
DEVLINK_DPIPE_HEADER_IPV4,
+ DEVLINK_DPIPE_HEADER_IPV6,
};
#endif /* _UAPI_LINUX_DEVLINK_H_ */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 194708a..47931a2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -63,6 +63,23 @@ struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
};
EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
+static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
+ {
+ .name = "destination ip",
+ .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
+ .bitwidth = 128,
+ },
+};
+
+struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
+ .name = "ipv6",
+ .id = DEVLINK_DPIPE_HEADER_IPV6,
+ .fields = devlink_dpipe_fields_ipv6,
+ .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
+ .global = true,
+};
+EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
+
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
static LIST_HEAD(devlink_list);
--
2.9.3
^ permalink raw reply related
* [patch net-next 0/8] mlxsw: Add IPv6 host dpipe table
From: Jiri Pirko @ 2017-08-30 12:02 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
From: Jiri Pirko <jiri@mellanox.com>
Arkadi says:
This patchset adds IPv6 host dpipe table support. This will provide the
ability to observe the hardware offloaded IPv6 neighbors.
Arkadi Sharshevsky (8):
devlink: Add IPv6 header for dpipe
mlxsw: spectrum_router: Export IPv6 link local address check helper
mlxsw: spectrum_dpipe: Add IPv6 host table initial support
mlxsw: spectrum_router: Add IPv6 neighbor access helper
mlxsw: spectrum_dpipe: Make host entry fill handler more generic
mlxsw: spectrum_dpipe: Add support for IPv6 host table dump
mlxsw: spectrum_router: Add support for setting counters on IPv6
neighbors
mlxsw: spectrum_dpipe: Add support for controlling IPv6 neighbor
counters
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 182 ++++++++++++++++++---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.h | 1 +
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 37 ++++-
.../net/ethernet/mellanox/mlxsw/spectrum_router.h | 3 +
include/net/devlink.h | 1 +
include/uapi/linux/devlink.h | 5 +
net/core/devlink.c | 17 ++
7 files changed, 219 insertions(+), 27 deletions(-)
--
2.9.3
^ permalink raw reply
* Re: Question about ip_defrag
From: Florian Westphal @ 2017-08-30 11:58 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Florian Westphal, liujian (CE), davem@davemloft.net,
edumazet@google.com, netdev@vger.kernel.org, Wangkefeng (Kevin),
weiyongjun (A)
In-Reply-To: <20170830125843.250c91c1@redhat.com>
Jesper Dangaard Brouer <brouer@redhat.com> wrote:
> > I take 2) back. Its wrong to do this, for large NR_CPU values it
> > would even overflow.
>
> Alternatively solution 3:
> Why do we want to maintain a (4MBytes) memory limit, across all CPUs?
> Couldn't we just allow each CPU to have a memory limit?
Consider ipv4, ipv6, nf ipv6 defrag, 6lowpan, and 8k cpus... This will
render any limit useless.
> > > To me it looks like we/I have been using the wrong API for comparing
> > > against percpu_counters. I guess we should have used __percpu_counter_compare().
> >
> > Are you sure? For liujian use case (64 cores) it looks like we would
> > always fall through to percpu_counter_sum() so we eat spinlock_irqsave
> > cost for all compares.
> >
> > Before we entertain this we should consider reducing frag_percpu_counter_batch
> > to a smaller value.
>
> Yes, I agree, we really need to lower/reduce the frag_percpu_counter_batch.
> As you say, else the __percpu_counter_compare() call will be useless
> (around systems with >= 32 CPUs).
>
> I think the bug is in frag_mem_limit(). It just reads the global
> counter (fbc->count), without considering other CPUs can have upto 130K
> that haven't been subtracted yet (due to 3M low limit, become dangerous
> at >=24 CPUs). The __percpu_counter_compare() does the right thing,
> and takes into account the number of (online) CPUs and batch size, to
> account for this.
Right, I think we should at very least use __percpu_counter_compare
before denying a new frag queue allocation request.
I'll create a patch.
^ permalink raw reply
* [PATCH] RDS: constify rhashtable_params
From: Arvind Yadav @ 2017-08-30 11:49 UTC (permalink / raw)
To: davem, santosh.shilimkar; +Cc: linux-kernel, rds-devel, linux-rdma, netdev
rhashtable_params are not supposed to change at runtime. All
Functions rhashtable_* working with const rhashtable_params
provided by <linux/rhashtable.h>. So mark the non-const structs
as const.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
net/rds/bind.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 3a915be..75d43dc 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -40,7 +40,7 @@
static struct rhashtable bind_hash_table;
-static struct rhashtable_params ht_parms = {
+static const struct rhashtable_params ht_parms = {
.nelem_hint = 768,
.key_len = sizeof(u64),
.key_offset = offsetof(struct rds_sock, rs_bound_key),
--
1.9.1
^ permalink raw reply related
* [PATCH] netfilter: nat: constify rhashtable_params
From: Arvind Yadav @ 2017-08-30 11:48 UTC (permalink / raw)
To: davem, fw, kadlec, pablo; +Cc: linux-kernel, netdev, coreteam, netfilter-devel
rhashtable_params are not supposed to change at runtime. All
Functions rhashtable_* working with const rhashtable_params
provided by <linux/rhashtable.h>. So mark the non-const structs
as const.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
net/netfilter/nf_nat_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index eb54178..d1f355e 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -198,7 +198,7 @@ static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
return 0;
}
-static struct rhashtable_params nf_nat_bysource_params = {
+static const struct rhashtable_params nf_nat_bysource_params = {
.head_offset = offsetof(struct nf_conn, nat_bysource),
.obj_hashfn = nf_nat_bysource_hash,
.obj_cmpfn = nf_nat_bysource_cmp,
--
1.9.1
^ permalink raw reply related
* [PATCH][next][V2] bpf: test_maps: fix typo "conenct" -> "connect"
From: Colin King @ 2017-08-30 11:47 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Shuah Khan, netdev,
linux-kselftest
Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to typo in printf error message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
tools/testing/selftests/bpf/test_maps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 7059bb315a10..8fdaf2e21c8a 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -525,7 +525,7 @@ static void test_sockmap(int tasks, void *data)
addr.sin_port = htons(ports[i - 2]);
err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
if (err) {
- printf("failed to conenct\n");
+ printf("failed to connect\n");
goto out;
}
}
--
2.14.1
^ permalink raw reply related
* [PATCH][next] bpf: test_maps: fix typo "conenct" -> "connext"
From: Colin King @ 2017-08-30 11:47 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Shuah Khan, netdev,
linux-kselftest
Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to typo in printf error message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
tools/testing/selftests/bpf/test_maps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 7059bb315a10..8fdaf2e21c8a 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -525,7 +525,7 @@ static void test_sockmap(int tasks, void *data)
addr.sin_port = htons(ports[i - 2]);
err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
if (err) {
- printf("failed to conenct\n");
+ printf("failed to connect\n");
goto out;
}
}
--
2.14.1
^ permalink raw reply related
* [PATCH][next] qed: fix spelling mistake: "calescing" -> "coalescing"
From: Colin King @ 2017-08-30 11:40 UTC (permalink / raw)
To: Yuval Mintz, Ariel Elior, everest-linux-l2, netdev; +Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to spelling mistake in DP_NOTICE message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 9a1645852015..085338990f49 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -2805,7 +2805,7 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
p_hwfn = p_cid->p_owner;
rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
if (rc)
- DP_NOTICE(p_hwfn, "Unable to read queue calescing\n");
+ DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
return rc;
}
--
2.14.1
^ permalink raw reply related
* RE: [PATCH net-next v2] net: bcmgenet: Use correct I/O accessors
From: David Laight @ 2017-08-30 11:39 UTC (permalink / raw)
To: 'Florian Fainelli', netdev@vger.kernel.org
Cc: davem@davemloft.net, opendmb@gmail.com, jaedon.shin@gmail.com
In-Reply-To: <1504034731-31613-1-git-send-email-f.fainelli@gmail.com>
From: Florian Fainelli
> Sent: 29 August 2017 20:26
> The GENET driver currently uses __raw_{read,write}l which means
> native I/O endian. This works correctly for an ARM LE kernel (default)
> but fails miserably on an ARM BE (BE8) kernel where registers are kept
> little endian, so replace uses with {read,write}l_relaxed here which is
> what we want because this is all performance sensitive code.
...
> + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
> + __raw_writel(value, offset);
> + else
> + writel_relaxed(value, offset);
How do you know that all BE MIPS that might have this driver have
the BE registers of your card?
(Or that all ARM BE systems have LE registers.)
If nothing else the driver code should be predicated on a
condition set by the kernel config that depends on the cpu build
rather than embedding that condition in a lot of drivers
David
^ 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;
as well as URLs for NNTP newsgroup(s).