* [PATCH v4 net-next 2/3] ip6_gre: Refactor ip6gre xmit codes
From: William Tu @ 2017-11-30 19:26 UTC (permalink / raw)
To: netdev
In-Reply-To: <1512069970-4571-1-git-send-email-u9012063@gmail.com>
This patch refactors the ip6gre_xmit_{ipv4, ipv6}.
It is a prep work to add the ip6erspan tunnel.
Signed-off-by: William Tu <u9012063@gmail.com>
---
net/ipv6/ip6_gre.c | 123 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 75 insertions(+), 48 deletions(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 4cfd8e0696fe..907d2e8405e2 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -496,6 +496,78 @@ static int gre_handle_offloads(struct sk_buff *skb, bool csum)
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
+static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi6 *fl6, __u8 *dsfield,
+ int *encap_limit)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+
+ if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+ *encap_limit = t->parms.encap_limit;
+
+ memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6));
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
+ *dsfield = ipv4_get_dsfield(iph);
+ else
+ *dsfield = ip6_tclass(t->parms.flowinfo);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
+ fl6->flowi6_mark = skb->mark;
+ else
+ fl6->flowi6_mark = t->parms.fwmark;
+
+ fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+}
+
+static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi6 *fl6, __u8 *dsfield,
+ int *encap_limit)
+{
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+ __u16 offset;
+
+ offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+ /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+
+ if (offset > 0) {
+ struct ipv6_tlv_tnl_enc_lim *tel;
+
+ tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
+ if (tel->encap_limit == 0) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_HDR_FIELD, offset + 2);
+ return -1;
+ }
+ *encap_limit = tel->encap_limit - 1;
+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
+ *encap_limit = t->parms.encap_limit;
+ }
+
+ memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6));
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
+ *dsfield = ipv6_get_dsfield(ipv6h);
+ else
+ *dsfield = ip6_tclass(t->parms.flowinfo);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
+ fl6->flowlabel |= ip6_flowlabel(ipv6h);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
+ fl6->flowi6_mark = skb->mark;
+ else
+ fl6->flowi6_mark = t->parms.fwmark;
+
+ fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
+ return 0;
+}
+
static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
struct net_device *dev, __u8 dsfield,
struct flowi6 *fl6, int encap_limit,
@@ -527,7 +599,6 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
{
struct ip6_tnl *t = netdev_priv(dev);
- const struct iphdr *iph = ip_hdr(skb);
int encap_limit = -1;
struct flowi6 fl6;
__u8 dsfield;
@@ -536,21 +607,7 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
- encap_limit = t->parms.encap_limit;
-
- memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- dsfield = ipv4_get_dsfield(iph);
- else
- dsfield = ip6_tclass(t->parms.flowinfo);
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fl6.flowi6_mark = skb->mark;
- else
- fl6.flowi6_mark = t->parms.fwmark;
-
- fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ prepare_ip6gre_xmit_ipv4(skb, dev, &fl6, &dsfield, &encap_limit);
err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM));
if (err)
@@ -574,7 +631,6 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
struct ip6_tnl *t = netdev_priv(dev);
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
int encap_limit = -1;
- __u16 offset;
struct flowi6 fl6;
__u8 dsfield;
__u32 mtu;
@@ -583,37 +639,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr))
return -1;
- offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
- /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
- ipv6h = ipv6_hdr(skb);
-
- if (offset > 0) {
- struct ipv6_tlv_tnl_enc_lim *tel;
- tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
- if (tel->encap_limit == 0) {
- icmpv6_send(skb, ICMPV6_PARAMPROB,
- ICMPV6_HDR_FIELD, offset + 2);
- return -1;
- }
- encap_limit = tel->encap_limit - 1;
- } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
- encap_limit = t->parms.encap_limit;
-
- memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- dsfield = ipv6_get_dsfield(ipv6h);
- else
- dsfield = ip6_tclass(t->parms.flowinfo);
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
- fl6.flowlabel |= ip6_flowlabel(ipv6h);
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fl6.flowi6_mark = skb->mark;
- else
- fl6.flowi6_mark = t->parms.fwmark;
-
- fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ if (prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit))
+ return -1;
if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)))
return -1;
--
2.7.4
^ permalink raw reply related
* [PATCH v4 net-next 3/3] ip6_gre: Add ERSPAN native tunnel support
From: William Tu @ 2017-11-30 19:26 UTC (permalink / raw)
To: netdev
In-Reply-To: <1512069970-4571-1-git-send-email-u9012063@gmail.com>
The patch adds support for ERSPAN tunnel over ipv6.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/ip6_tunnel.h | 1 +
net/ipv6/ip6_gre.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 267 insertions(+), 4 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index d66f70f63734..109a5a8877ef 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -36,6 +36,7 @@ struct __ip6_tnl_parm {
__be32 o_key;
__u32 fwmark;
+ __u32 index; /* ERSPAN type II index */
};
/* IPv6 tunnel */
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 907d2e8405e2..76379f01bcd2 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -55,6 +55,7 @@
#include <net/ip6_route.h>
#include <net/ip6_tunnel.h>
#include <net/gre.h>
+#include <net/erspan.h>
static bool log_ecn_error = true;
@@ -73,6 +74,7 @@ struct ip6gre_net {
static struct rtnl_link_ops ip6gre_link_ops __read_mostly;
static struct rtnl_link_ops ip6gre_tap_ops __read_mostly;
+static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly;
static int ip6gre_tunnel_init(struct net_device *dev);
static void ip6gre_tunnel_setup(struct net_device *dev);
static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t);
@@ -121,7 +123,8 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
unsigned int h1 = HASH_KEY(key);
struct ip6_tnl *t, *cand = NULL;
struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
- int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
+ int dev_type = (gre_proto == htons(ETH_P_TEB) ||
+ gre_proto == htons(ETH_P_ERSPAN)) ?
ARPHRD_ETHER : ARPHRD_IP6GRE;
int score, cand_score = 4;
@@ -468,6 +471,41 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
return PACKET_REJECT;
}
+static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
+ struct tnl_ptk_info *tpi)
+{
+ const struct ipv6hdr *ipv6h;
+ struct erspanhdr *ershdr;
+ struct ip6_tnl *tunnel;
+ __be32 index;
+
+ ipv6h = ipv6_hdr(skb);
+ ershdr = (struct erspanhdr *)skb->data;
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
+ return PACKET_REJECT;
+
+ tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
+ index = ershdr->md.index;
+
+ tunnel = ip6gre_tunnel_lookup(skb->dev,
+ &ipv6h->saddr, &ipv6h->daddr, tpi->key,
+ tpi->proto);
+ if (tunnel) {
+ if (__iptunnel_pull_header(skb, sizeof(*ershdr),
+ htons(ETH_P_TEB),
+ false, false) < 0)
+ return PACKET_REJECT;
+
+ tunnel->parms.index = ntohl(index);
+ ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
+
+ return PACKET_RCVD;
+ }
+
+ return PACKET_REJECT;
+}
+
static int gre_rcv(struct sk_buff *skb)
{
struct tnl_ptk_info tpi;
@@ -481,6 +519,12 @@ static int gre_rcv(struct sk_buff *skb)
if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
goto drop;
+ if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
+ if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD)
+ return 0;
+ goto drop;
+ }
+
if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD)
return 0;
@@ -732,6 +776,88 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct net_device_stats *stats;
+ bool truncate = false;
+ int encap_limit = -1;
+ __u8 dsfield = false;
+ struct flowi6 fl6;
+ int err = -EINVAL;
+ __u32 mtu;
+
+ if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
+ goto tx_err;
+
+ if (gre_handle_offloads(skb, false))
+ goto tx_err;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ prepare_ip6gre_xmit_ipv4(skb, dev, &fl6,
+ &dsfield, &encap_limit);
+ break;
+ case htons(ETH_P_IPV6):
+ if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr))
+ goto tx_err;
+ if (prepare_ip6gre_xmit_ipv6(skb, dev, &fl6,
+ &dsfield, &encap_limit))
+ goto tx_err;
+ break;
+ default:
+ memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
+ break;
+ }
+
+ if (skb->len > dev->mtu + dev->hard_header_len) {
+ pskb_trim(skb, dev->mtu + dev->hard_header_len);
+ truncate = true;
+ }
+
+ erspan_build_header(skb, t->parms.o_key, t->parms.index,
+ truncate, false);
+ t->parms.o_flags &= ~TUNNEL_KEY;
+
+ IPCB(skb)->flags = 0;
+ fl6.daddr = t->parms.raddr;
+
+ /* Push GRE header. */
+ gre_build_header(skb, 8, TUNNEL_SEQ,
+ htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++));
+
+ /* TooBig packet may have updated dst->dev's mtu */
+ if (dst && dst_mtu(dst) > dst->dev->mtu)
+ dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
+
+ err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
+ NEXTHDR_GRE);
+ if (err != 0) {
+ /* XXX: send ICMP error even if DF is not set. */
+ if (err == -EMSGSIZE) {
+ if (skb->protocol == htons(ETH_P_IP))
+ icmp_send(skb, ICMP_DEST_UNREACH,
+ ICMP_FRAG_NEEDED, htonl(mtu));
+ else
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ }
+
+ goto tx_err;
+ }
+ return NETDEV_TX_OK;
+
+tx_err:
+ stats = &t->dev->stats;
+ stats->tx_errors++;
+ stats->tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
{
struct net_device *dev = t->dev;
@@ -1111,7 +1237,6 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
dev_hold(dev);
}
-
static struct inet6_protocol ip6gre_protocol __read_mostly = {
.handler = gre_rcv,
.err_handler = ip6gre_err,
@@ -1126,7 +1251,8 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
for_each_netdev_safe(net, dev, aux)
if (dev->rtnl_link_ops == &ip6gre_link_ops ||
- dev->rtnl_link_ops == &ip6gre_tap_ops)
+ dev->rtnl_link_ops == &ip6gre_tap_ops ||
+ dev->rtnl_link_ops == &ip6erspan_tap_ops)
unregister_netdevice_queue(dev, head);
for (prio = 0; prio < 4; prio++) {
@@ -1248,6 +1374,47 @@ static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
return ip6gre_tunnel_validate(tb, data, extack);
}
+static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ __be16 flags = 0;
+ int ret;
+
+ if (!data)
+ return 0;
+
+ ret = ip6gre_tap_validate(tb, data, extack);
+ if (ret)
+ return ret;
+
+ /* ERSPAN should only have GRE sequence and key flag */
+ if (data[IFLA_GRE_OFLAGS])
+ flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
+ if (data[IFLA_GRE_IFLAGS])
+ flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
+ if (!data[IFLA_GRE_COLLECT_METADATA] &&
+ flags != (GRE_SEQ | GRE_KEY))
+ return -EINVAL;
+
+ /* ERSPAN Session ID only has 10-bit. Since we reuse
+ * 32-bit key field as ID, check it's range.
+ */
+ if (data[IFLA_GRE_IKEY] &&
+ (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
+ return -EINVAL;
+
+ if (data[IFLA_GRE_OKEY] &&
+ (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
+ return -EINVAL;
+
+ if (data[IFLA_GRE_ERSPAN_INDEX]) {
+ u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+
+ if (index & ~INDEX_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
static void ip6gre_netlink_parms(struct nlattr *data[],
struct __ip6_tnl_parm *parms)
@@ -1294,6 +1461,9 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
if (data[IFLA_GRE_FWMARK])
parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
+
+ if (data[IFLA_GRE_ERSPAN_INDEX])
+ parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
}
static int ip6gre_tap_init(struct net_device *dev)
@@ -1330,6 +1500,59 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
NETIF_F_HIGHDMA | \
NETIF_F_HW_CSUM)
+static int ip6erspan_tap_init(struct net_device *dev)
+{
+ struct ip6_tnl *tunnel;
+ int t_hlen;
+ int ret;
+
+ tunnel = netdev_priv(dev);
+
+ tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
+ strcpy(tunnel->parms.name, dev->name);
+
+ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!dev->tstats)
+ return -ENOMEM;
+
+ ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+ if (ret) {
+ free_percpu(dev->tstats);
+ dev->tstats = NULL;
+ return ret;
+ }
+
+ tunnel->tun_hlen = 8;
+ tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
+ sizeof(struct erspanhdr);
+ t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
+
+ dev->hard_header_len = LL_MAX_HEADER + t_hlen;
+ dev->mtu = ETH_DATA_LEN - t_hlen;
+ if (dev->type == ARPHRD_ETHER)
+ dev->mtu -= ETH_HLEN;
+ if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+ dev->mtu -= 8;
+
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ tunnel = netdev_priv(dev);
+ ip6gre_tnl_link_config(tunnel, 1);
+
+ return 0;
+}
+
+static const struct net_device_ops ip6erspan_netdev_ops = {
+ .ndo_init = ip6erspan_tap_init,
+ .ndo_uninit = ip6gre_tunnel_uninit,
+ .ndo_start_xmit = ip6erspan_tunnel_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = ip6_tnl_change_mtu,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_get_iflink = ip6_tnl_get_iflink,
+};
+
static void ip6gre_tap_setup(struct net_device *dev)
{
@@ -1521,6 +1744,8 @@ static size_t ip6gre_get_size(const struct net_device *dev)
nla_total_size(2) +
/* IFLA_GRE_FWMARK */
nla_total_size(4) +
+ /* IFLA_GRE_ERSPAN_INDEX */
+ nla_total_size(4) +
0;
}
@@ -1542,7 +1767,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) ||
nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) ||
- nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark))
+ nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) ||
+ nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
goto nla_put_failure;
if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
@@ -1578,8 +1804,23 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
[IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
[IFLA_GRE_FWMARK] = { .type = NLA_U32 },
+ [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 },
};
+static void ip6erspan_tap_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+
+ dev->netdev_ops = &ip6erspan_netdev_ops;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = ip6gre_dev_free;
+
+ dev->features |= NETIF_F_NETNS_LOCAL;
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ netif_keep_dst(dev);
+}
+
static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
.kind = "ip6gre",
.maxtype = IFLA_GRE_MAX,
@@ -1609,6 +1850,20 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
.get_link_net = ip6_tnl_get_link_net,
};
+static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = {
+ .kind = "ip6erspan",
+ .maxtype = IFLA_GRE_MAX,
+ .policy = ip6gre_policy,
+ .priv_size = sizeof(struct ip6_tnl),
+ .setup = ip6erspan_tap_setup,
+ .validate = ip6erspan_tap_validate,
+ .newlink = ip6gre_newlink,
+ .changelink = ip6gre_changelink,
+ .get_size = ip6gre_get_size,
+ .fill_info = ip6gre_fill_info,
+ .get_link_net = ip6_tnl_get_link_net,
+};
+
/*
* And now the modules code and kernel interface.
*/
@@ -1637,9 +1892,15 @@ static int __init ip6gre_init(void)
if (err < 0)
goto tap_ops_failed;
+ err = rtnl_link_register(&ip6erspan_tap_ops);
+ if (err < 0)
+ goto erspan_link_failed;
+
out:
return err;
+erspan_link_failed:
+ rtnl_link_unregister(&ip6gre_tap_ops);
tap_ops_failed:
rtnl_link_unregister(&ip6gre_link_ops);
rtnl_link_failed:
@@ -1653,6 +1914,7 @@ static void __exit ip6gre_fini(void)
{
rtnl_link_unregister(&ip6gre_tap_ops);
rtnl_link_unregister(&ip6gre_link_ops);
+ rtnl_link_unregister(&ip6erspan_tap_ops);
inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE);
unregister_pernet_device(&ip6gre_net_ops);
}
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v4 net-next 0/3]
From: David Miller @ 2017-11-30 19:32 UTC (permalink / raw)
To: u9012063; +Cc: netdev
In-Reply-To: <1512069970-4571-1-git-send-email-u9012063@gmail.com>
There is no actual descriptive text in your Subject line here.
Please fix this.
^ permalink raw reply
* Re: [PATCH] rxrpc: Neaten logging macros and add KERN_DEBUG logging level
From: David Howells @ 2017-11-30 19:34 UTC (permalink / raw)
To: Joe Perches; +Cc: dhowells, David Miller, linux-kernel, netdev, linux-afs
In-Reply-To: <1512065211.19952.112.camel@perches.com>
Joe Perches <joe@perches.com> wrote:
> There is no listed rxrpc maintainer.
There's a script in the kernel called get_maintainer.pl which you might find
of use:
warthog>./scripts/get_maintainer.pl net/rxrpc/
"David S. Miller" <davem@davemloft.net> (maintainer:NETWORKING [GENERAL],commit_signer:23/74=31%)
David Howells <dhowells@redhat.com> (commit_signer:64/74=86%,authored:60/74=81%)
netdev@vger.kernel.org (open list:NETWORKING [GENERAL])
linux-kernel@vger.kernel.org (open list)
It would seem a good idea to cc me, as the one with the largest "authored"
also.
David
^ permalink raw reply
* [PATCH 0/2] net: ethtool: add support for ETH_RESET_AP
From: Scott Branden @ 2017-11-30 19:35 UTC (permalink / raw)
To: David S. Miller, Allan W. Nielsen, Andrew Lunn, Raju Lakkaraju,
Florian Fainelli
Cc: BCM Kernel Feedback, linux-kernel, Steve Lin, netdev,
Michael Chan, Scott Branden
Add support to reset appplication processors inside SmartNICs by
defining new ETH_RESET_AP bit.
And use new ETH_RESET_AP bit in bnxt ethernet driver.
Scott Branden (2):
net: ethtool: add support for reset of AP inside NIC interface.
bnxt_en: Add ETH_RESET_AP support
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 11 +++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 1 +
include/uapi/linux/ethtool.h | 1 +
3 files changed, 13 insertions(+)
--
2.5.0
^ permalink raw reply
* [PATCH 1/2] net: ethtool: add support for reset of AP inside NIC interface.
From: Scott Branden @ 2017-11-30 19:35 UTC (permalink / raw)
To: David S. Miller, Allan W. Nielsen, Andrew Lunn, Raju Lakkaraju,
Florian Fainelli
Cc: BCM Kernel Feedback, linux-kernel, Steve Lin, netdev,
Michael Chan, Scott Branden
In-Reply-To: <1512070560-16739-1-git-send-email-scott.branden@broadcom.com>
Add ETH_RESET_AP to reset the application processor(s) inside the NIC
interface.
Current ETH_RESET_MGMT supports a management processor inside this NIC.
This is typically used for remote NIC management purposes.
Application processors exist inside some SmartNICs to run various
applications inside the NIC processor - be it a simple algorithm without
an OS to as complex as hosting multiple VMs.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
include/uapi/linux/ethtool.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index ac71559..44a0b67 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1686,6 +1686,7 @@ enum ethtool_reset_flags {
ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */
ETH_RESET_RAM = 1 << 7, /* RAM shared between
* multiple components */
+ ETH_RESET_AP = 1 << 8, /* Application processor */
ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to
* this interface */
--
2.5.0
^ permalink raw reply related
* [PATCH 2/2] bnxt_en: Add ETH_RESET_AP support
From: Scott Branden @ 2017-11-30 19:36 UTC (permalink / raw)
To: David S. Miller, Allan W. Nielsen, Andrew Lunn, Raju Lakkaraju,
Florian Fainelli
Cc: BCM Kernel Feedback, linux-kernel, Steve Lin, netdev,
Michael Chan, Scott Branden
In-Reply-To: <1512070560-16739-1-git-send-email-scott.branden@broadcom.com>
Add ETH_RESET_AP support handling to reset the internal
Application Processor(s) of the SmartNIC card.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 11 +++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 7ce1d4b..fc2c483 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -1376,6 +1376,9 @@ static int bnxt_firmware_reset(struct net_device *dev,
req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP;
req.selfrst_status = FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP;
break;
+ case BNXT_FW_RESET_AP:
+ req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_AP;
+ break;
default:
return -EINVAL;
}
@@ -2522,6 +2525,14 @@ static int bnxt_reset(struct net_device *dev, u32 *flags)
rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_CHIP);
if (!rc)
netdev_info(dev, "Reset request successful. Reload driver to complete reset\n");
+ } else if (*flags == ETH_RESET_AP) {
+ /* This feature is not supported in older firmware versions */
+ if (bp->hwrm_spec_code < 0x10803)
+ return -EOPNOTSUPP;
+
+ rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_AP);
+ if (!rc)
+ netdev_info(dev, "Reset Application Processor request successful.\n");
} else {
rc = -EINVAL;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
index ff601b4..836ef68 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
@@ -34,6 +34,7 @@ struct bnxt_led_cfg {
#define BNXT_LED_DFLT_ENABLES(x) \
cpu_to_le32(BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (x)))
+#define BNXT_FW_RESET_AP 0xfffe
#define BNXT_FW_RESET_CHIP 0xffff
extern const struct ethtool_ops bnxt_ethtool_ops;
--
2.5.0
^ permalink raw reply related
* Re: [PATCH v4 net-next 0/3]
From: William Tu @ 2017-11-30 19:41 UTC (permalink / raw)
To: David Miller; +Cc: Linux Kernel Network Developers
In-Reply-To: <20171130.143201.1466268631938509780.davem@davemloft.net>
On Thu, Nov 30, 2017 at 11:32 AM, David Miller <davem@davemloft.net> wrote:
>
> There is no actual descriptive text in your Subject line here.
>
> Please fix this.
sure. thanks. Let me resubmit.
^ permalink raw reply
* Re: [PATCH 2/2] bnxt_en: Add ETH_RESET_AP support
From: Michael Chan @ 2017-11-30 19:44 UTC (permalink / raw)
To: Scott Branden
Cc: David S. Miller, Allan W. Nielsen, Andrew Lunn, Raju Lakkaraju,
Florian Fainelli, BCM Kernel Feedback, open list, Steve Lin,
Netdev
In-Reply-To: <1512070560-16739-3-git-send-email-scott.branden@broadcom.com>
On Thu, Nov 30, 2017 at 11:36 AM, Scott Branden
<scott.branden@broadcom.com> wrote:
> Add ETH_RESET_AP support handling to reset the internal
> Application Processor(s) of the SmartNIC card.
>
> Signed-off-by: Scott Branden <scott.branden@broadcom.com>
Acked-by: Michael Chan <michael.chan@broadcom.com>
^ permalink raw reply
* Re: [PATCH] rxrpc: Neaten logging macros and add KERN_DEBUG logging level
From: Joe Perches @ 2017-11-30 19:46 UTC (permalink / raw)
To: David Howells; +Cc: David Miller, linux-kernel, netdev, linux-afs
In-Reply-To: <25765.1512070491@warthog.procyon.org.uk>
On Thu, 2017-11-30 at 19:34 +0000, David Howells wrote:
> Joe Perches <joe@perches.com> wrote:
>
> > There is no listed rxrpc maintainer.
>
> There's a script in the kernel called get_maintainer.pl which you might find
> of use:
Yeah, I've heard of it. I also wrote it btw.
> warthog>./scripts/get_maintainer.pl net/rxrpc/
> "David S. Miller" <davem@davemloft.net> (maintainer:NETWORKING [GENERAL],commit_signer:23/74=31%)
> David Howells <dhowells@redhat.com> (commit_signer:64/74=86%,authored:60/74=81%)
> netdev@vger.kernel.org (open list:NETWORKING [GENERAL])
> linux-kernel@vger.kernel.org (open list)
The script I use to send patches does not cc
patch authors as, based on my history
sending patches, most to many of them do not
want to see patches.
> It would seem a good idea to cc me, as the one with the largest "authored"
> also.
Perhaps a better idea would be to have an
rxrpc section in the MAINTAINERS file.
cheers, Joe
^ permalink raw reply
* [PATCH net-next] net: llc: remove init_net check
From: Alexander Aring @ 2017-11-30 19:45 UTC (permalink / raw)
To: davem; +Cc: hadi, netdev, Alexander Aring
Commit e730c15519d09 ("[NET]: Make packet reception network namespace
safe") added several init_net compares to protocols with unknown
net namespace support. The idea was as users started using the different
protocols they would test and enable them.
In our use-case we generate STP enabled Linux bridges in different
namespaces. The bridges are connected via veth interfaces.
This patch makes STP work in such a setup.
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
net/llc/llc_input.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 82cb93f66b9b..09b530d90610 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -14,7 +14,6 @@
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/export.h>
-#include <net/net_namespace.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
@@ -162,9 +161,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
void (*sta_handler)(struct sk_buff *skb);
void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
- if (!net_eq(dev_net(dev), &init_net))
- goto drop;
-
/*
* When the interface is in promisc. mode, drop all the crap that it
* receives, do not try to analyse it.
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 0/3] ip6_gre: add erspan native tunnel for ipv6
From: William Tu @ 2017-11-30 19:51 UTC (permalink / raw)
To: netdev
The patch series add support for ERSPAN tunnel over ipv6. The first patch
refectors the existing ipv4 gre implementation and the second refactors the
ipv6 gre's xmit code. Finally the last patch introduces erspan protocol.
change in v5:
- add cover-letter description
change in v4:
- rebase on top of net-next
- use log_ecn_error in ip6_tnl_rcv
change in v3:
- add inline for functions in header
- rebase on top of net-next
change in v2:
- remove inline
- fix some indent
- fix errors reports by clang and scan-build
William Tu (3):
ip_gre: Refector the erpsan tunnel code.
ip6_gre: Refactor ip6gre xmit codes
ip6_gre: Add ERSPAN native tunnel support
include/net/erspan.h | 51 ++++++
include/net/ip6_tunnel.h | 1 +
net/ipv4/ip_gre.c | 54 +------
net/ipv6/ip6_gre.c | 393 ++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 398 insertions(+), 101 deletions(-)
--
A test script is provided below:
#!/bin/bash
# In the namespace NS0, create veth0 and ip6erspan00
# Out of the namespace, create veth1 and ip6erspan11
# Ping in and out of namespace using ERSPAN protocol
# Patch v2 for iproute2
# https://marc.info/?l=linux-netdev&m=151002165705772&w=2
cleanup() {
set +ex
ip netns del ns0
ip link del ip6erspan11
ip link del veth1
}
main() {
trap cleanup 0 2 3 9
ip netns add ns0
ip link add veth0 type veth peer name veth1
ip link set veth0 netns ns0
# non-namespace
ip addr add dev veth1 fc00:100::2/96
ip link add dev ip6erspan11 type ip6erspan seq key 102 erspan 123 \
local fc00:100::2 \
remote fc00:100::1
ip addr add dev ip6erspan11 fc00:200::2/96
ip addr add dev ip6erspan11 10.10.200.2/24
# namespace: ns0
ip netns exec ns0 ip addr add fc00:100::1/96 dev veth0
# Tunnel
ip netns exec ns0 ip link add dev ip6erspan00 type ip6erspan seq key 102 erspan 12 \
local fc00:100::1 \
remote fc00:100::2
ip netns exec ns0 ip addr add dev ip6erspan00 fc00:200::1/96
ip netns exec ns0 ip addr add dev ip6erspan00 10.10.200.1/24
ip link set dev veth1 up
ip link set dev ip6erspan11 up
ip netns exec ns0 ip link set dev ip6erspan00 up
ip netns exec ns0 ip link set dev veth0 up
}
main
# Ping underlying
ping6 -c 1 fc00:100::1 || true
# ping overlay
ping -c 3 10.10.200.1
ping6 -c 3 fc00:200::1
--
2.7.4
^ permalink raw reply
* [PATCH v5 net-next 1/3] ip_gre: Refector the erpsan tunnel code.
From: William Tu @ 2017-11-30 19:51 UTC (permalink / raw)
To: netdev
In-Reply-To: <1512071489-5318-1-git-send-email-u9012063@gmail.com>
Move two erspan functions to header file, erspan.h, so ipv6
erspan implementation can use it.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/erspan.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/ip_gre.c | 54 +++++-----------------------------------------------
2 files changed, 56 insertions(+), 49 deletions(-)
diff --git a/include/net/erspan.h b/include/net/erspan.h
index ca94fc86865e..6e758d08c9ee 100644
--- a/include/net/erspan.h
+++ b/include/net/erspan.h
@@ -58,4 +58,55 @@ struct erspanhdr {
struct erspan_metadata md;
};
+static inline u8 tos_to_cos(u8 tos)
+{
+ u8 dscp, cos;
+
+ dscp = tos >> 2;
+ cos = dscp >> 3;
+ return cos;
+}
+
+static inline void erspan_build_header(struct sk_buff *skb,
+ __be32 id, u32 index,
+ bool truncate, bool is_ipv4)
+{
+ struct ethhdr *eth = eth_hdr(skb);
+ enum erspan_encap_type enc_type;
+ struct erspanhdr *ershdr;
+ struct qtag_prefix {
+ __be16 eth_type;
+ __be16 tci;
+ } *qp;
+ u16 vlan_tci = 0;
+ u8 tos;
+
+ tos = is_ipv4 ? ip_hdr(skb)->tos :
+ (ipv6_hdr(skb)->priority << 4) +
+ (ipv6_hdr(skb)->flow_lbl[0] >> 4);
+
+ enc_type = ERSPAN_ENCAP_NOVLAN;
+
+ /* If mirrored packet has vlan tag, extract tci and
+ * perserve vlan header in the mirrored frame.
+ */
+ if (eth->h_proto == htons(ETH_P_8021Q)) {
+ qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
+ vlan_tci = ntohs(qp->tci);
+ enc_type = ERSPAN_ENCAP_INFRAME;
+ }
+
+ skb_push(skb, sizeof(*ershdr));
+ ershdr = (struct erspanhdr *)skb->data;
+ memset(ershdr, 0, sizeof(*ershdr));
+
+ ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
+ (ERSPAN_VERSION << VER_OFFSET));
+ ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
+ ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
+ (enc_type << EN_OFFSET & EN_MASK) |
+ ((truncate << T_OFFSET) & T_MASK));
+ ershdr->md.index = htonl(index & INDEX_MASK);
+}
+
#endif
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index bb6239169b1a..d828821d88d7 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -114,7 +114,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
static int ipgre_tunnel_init(struct net_device *dev);
static void erspan_build_header(struct sk_buff *skb,
- __be32 id, u32 index, bool truncate);
+ __be32 id, u32 index,
+ bool truncate, bool is_ipv4);
static unsigned int ipgre_net_id __read_mostly;
static unsigned int gre_tap_net_id __read_mostly;
@@ -589,7 +590,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
goto err_free_rt;
erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
- ntohl(md->index), truncate);
+ ntohl(md->index), truncate, true);
gre_build_header(skb, 8, TUNNEL_SEQ,
htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
@@ -668,52 +669,6 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-static inline u8 tos_to_cos(u8 tos)
-{
- u8 dscp, cos;
-
- dscp = tos >> 2;
- cos = dscp >> 3;
- return cos;
-}
-
-static void erspan_build_header(struct sk_buff *skb,
- __be32 id, u32 index, bool truncate)
-{
- struct iphdr *iphdr = ip_hdr(skb);
- struct ethhdr *eth = eth_hdr(skb);
- enum erspan_encap_type enc_type;
- struct erspanhdr *ershdr;
- struct qtag_prefix {
- __be16 eth_type;
- __be16 tci;
- } *qp;
- u16 vlan_tci = 0;
-
- enc_type = ERSPAN_ENCAP_NOVLAN;
-
- /* If mirrored packet has vlan tag, extract tci and
- * perserve vlan header in the mirrored frame.
- */
- if (eth->h_proto == htons(ETH_P_8021Q)) {
- qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
- vlan_tci = ntohs(qp->tci);
- enc_type = ERSPAN_ENCAP_INFRAME;
- }
-
- skb_push(skb, sizeof(*ershdr));
- ershdr = (struct erspanhdr *)skb->data;
- memset(ershdr, 0, sizeof(*ershdr));
-
- ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
- (ERSPAN_VERSION << VER_OFFSET));
- ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
- ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) |
- (enc_type << EN_OFFSET & EN_MASK) |
- ((truncate << T_OFFSET) & T_MASK));
- ershdr->md.index = htonl(index & INDEX_MASK);
-}
-
static netdev_tx_t erspan_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -737,7 +692,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
}
/* Push ERSPAN header */
- erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate);
+ erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
+ truncate, true);
tunnel->parms.o_flags &= ~TUNNEL_KEY;
__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
return NETDEV_TX_OK;
--
2.7.4
^ permalink raw reply related
* [PATCH v5 net-next 2/3] ip6_gre: Refactor ip6gre xmit codes
From: William Tu @ 2017-11-30 19:51 UTC (permalink / raw)
To: netdev
In-Reply-To: <1512071489-5318-1-git-send-email-u9012063@gmail.com>
This patch refactors the ip6gre_xmit_{ipv4, ipv6}.
It is a prep work to add the ip6erspan tunnel.
Signed-off-by: William Tu <u9012063@gmail.com>
---
net/ipv6/ip6_gre.c | 123 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 75 insertions(+), 48 deletions(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 4cfd8e0696fe..907d2e8405e2 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -496,6 +496,78 @@ static int gre_handle_offloads(struct sk_buff *skb, bool csum)
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
+static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi6 *fl6, __u8 *dsfield,
+ int *encap_limit)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+
+ if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+ *encap_limit = t->parms.encap_limit;
+
+ memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6));
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
+ *dsfield = ipv4_get_dsfield(iph);
+ else
+ *dsfield = ip6_tclass(t->parms.flowinfo);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
+ fl6->flowi6_mark = skb->mark;
+ else
+ fl6->flowi6_mark = t->parms.fwmark;
+
+ fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+}
+
+static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi6 *fl6, __u8 *dsfield,
+ int *encap_limit)
+{
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+ __u16 offset;
+
+ offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+ /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+
+ if (offset > 0) {
+ struct ipv6_tlv_tnl_enc_lim *tel;
+
+ tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
+ if (tel->encap_limit == 0) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_HDR_FIELD, offset + 2);
+ return -1;
+ }
+ *encap_limit = tel->encap_limit - 1;
+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
+ *encap_limit = t->parms.encap_limit;
+ }
+
+ memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6));
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
+ *dsfield = ipv6_get_dsfield(ipv6h);
+ else
+ *dsfield = ip6_tclass(t->parms.flowinfo);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
+ fl6->flowlabel |= ip6_flowlabel(ipv6h);
+
+ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
+ fl6->flowi6_mark = skb->mark;
+ else
+ fl6->flowi6_mark = t->parms.fwmark;
+
+ fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
+ return 0;
+}
+
static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
struct net_device *dev, __u8 dsfield,
struct flowi6 *fl6, int encap_limit,
@@ -527,7 +599,6 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
{
struct ip6_tnl *t = netdev_priv(dev);
- const struct iphdr *iph = ip_hdr(skb);
int encap_limit = -1;
struct flowi6 fl6;
__u8 dsfield;
@@ -536,21 +607,7 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
- encap_limit = t->parms.encap_limit;
-
- memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- dsfield = ipv4_get_dsfield(iph);
- else
- dsfield = ip6_tclass(t->parms.flowinfo);
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fl6.flowi6_mark = skb->mark;
- else
- fl6.flowi6_mark = t->parms.fwmark;
-
- fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ prepare_ip6gre_xmit_ipv4(skb, dev, &fl6, &dsfield, &encap_limit);
err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM));
if (err)
@@ -574,7 +631,6 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
struct ip6_tnl *t = netdev_priv(dev);
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
int encap_limit = -1;
- __u16 offset;
struct flowi6 fl6;
__u8 dsfield;
__u32 mtu;
@@ -583,37 +639,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr))
return -1;
- offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
- /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
- ipv6h = ipv6_hdr(skb);
-
- if (offset > 0) {
- struct ipv6_tlv_tnl_enc_lim *tel;
- tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
- if (tel->encap_limit == 0) {
- icmpv6_send(skb, ICMPV6_PARAMPROB,
- ICMPV6_HDR_FIELD, offset + 2);
- return -1;
- }
- encap_limit = tel->encap_limit - 1;
- } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
- encap_limit = t->parms.encap_limit;
-
- memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- dsfield = ipv6_get_dsfield(ipv6h);
- else
- dsfield = ip6_tclass(t->parms.flowinfo);
-
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
- fl6.flowlabel |= ip6_flowlabel(ipv6h);
- if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fl6.flowi6_mark = skb->mark;
- else
- fl6.flowi6_mark = t->parms.fwmark;
-
- fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+ if (prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit))
+ return -1;
if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)))
return -1;
--
2.7.4
^ permalink raw reply related
* [PATCH v5 net-next 3/3] ip6_gre: Add ERSPAN native tunnel support
From: William Tu @ 2017-11-30 19:51 UTC (permalink / raw)
To: netdev
In-Reply-To: <1512071489-5318-1-git-send-email-u9012063@gmail.com>
The patch adds support for ERSPAN tunnel over ipv6.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/ip6_tunnel.h | 1 +
net/ipv6/ip6_gre.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 267 insertions(+), 4 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index d66f70f63734..109a5a8877ef 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -36,6 +36,7 @@ struct __ip6_tnl_parm {
__be32 o_key;
__u32 fwmark;
+ __u32 index; /* ERSPAN type II index */
};
/* IPv6 tunnel */
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 907d2e8405e2..76379f01bcd2 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -55,6 +55,7 @@
#include <net/ip6_route.h>
#include <net/ip6_tunnel.h>
#include <net/gre.h>
+#include <net/erspan.h>
static bool log_ecn_error = true;
@@ -73,6 +74,7 @@ struct ip6gre_net {
static struct rtnl_link_ops ip6gre_link_ops __read_mostly;
static struct rtnl_link_ops ip6gre_tap_ops __read_mostly;
+static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly;
static int ip6gre_tunnel_init(struct net_device *dev);
static void ip6gre_tunnel_setup(struct net_device *dev);
static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t);
@@ -121,7 +123,8 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
unsigned int h1 = HASH_KEY(key);
struct ip6_tnl *t, *cand = NULL;
struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
- int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
+ int dev_type = (gre_proto == htons(ETH_P_TEB) ||
+ gre_proto == htons(ETH_P_ERSPAN)) ?
ARPHRD_ETHER : ARPHRD_IP6GRE;
int score, cand_score = 4;
@@ -468,6 +471,41 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
return PACKET_REJECT;
}
+static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
+ struct tnl_ptk_info *tpi)
+{
+ const struct ipv6hdr *ipv6h;
+ struct erspanhdr *ershdr;
+ struct ip6_tnl *tunnel;
+ __be32 index;
+
+ ipv6h = ipv6_hdr(skb);
+ ershdr = (struct erspanhdr *)skb->data;
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
+ return PACKET_REJECT;
+
+ tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
+ index = ershdr->md.index;
+
+ tunnel = ip6gre_tunnel_lookup(skb->dev,
+ &ipv6h->saddr, &ipv6h->daddr, tpi->key,
+ tpi->proto);
+ if (tunnel) {
+ if (__iptunnel_pull_header(skb, sizeof(*ershdr),
+ htons(ETH_P_TEB),
+ false, false) < 0)
+ return PACKET_REJECT;
+
+ tunnel->parms.index = ntohl(index);
+ ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
+
+ return PACKET_RCVD;
+ }
+
+ return PACKET_REJECT;
+}
+
static int gre_rcv(struct sk_buff *skb)
{
struct tnl_ptk_info tpi;
@@ -481,6 +519,12 @@ static int gre_rcv(struct sk_buff *skb)
if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
goto drop;
+ if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
+ if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD)
+ return 0;
+ goto drop;
+ }
+
if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD)
return 0;
@@ -732,6 +776,88 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct net_device_stats *stats;
+ bool truncate = false;
+ int encap_limit = -1;
+ __u8 dsfield = false;
+ struct flowi6 fl6;
+ int err = -EINVAL;
+ __u32 mtu;
+
+ if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
+ goto tx_err;
+
+ if (gre_handle_offloads(skb, false))
+ goto tx_err;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ prepare_ip6gre_xmit_ipv4(skb, dev, &fl6,
+ &dsfield, &encap_limit);
+ break;
+ case htons(ETH_P_IPV6):
+ if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr))
+ goto tx_err;
+ if (prepare_ip6gre_xmit_ipv6(skb, dev, &fl6,
+ &dsfield, &encap_limit))
+ goto tx_err;
+ break;
+ default:
+ memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
+ break;
+ }
+
+ if (skb->len > dev->mtu + dev->hard_header_len) {
+ pskb_trim(skb, dev->mtu + dev->hard_header_len);
+ truncate = true;
+ }
+
+ erspan_build_header(skb, t->parms.o_key, t->parms.index,
+ truncate, false);
+ t->parms.o_flags &= ~TUNNEL_KEY;
+
+ IPCB(skb)->flags = 0;
+ fl6.daddr = t->parms.raddr;
+
+ /* Push GRE header. */
+ gre_build_header(skb, 8, TUNNEL_SEQ,
+ htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++));
+
+ /* TooBig packet may have updated dst->dev's mtu */
+ if (dst && dst_mtu(dst) > dst->dev->mtu)
+ dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
+
+ err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
+ NEXTHDR_GRE);
+ if (err != 0) {
+ /* XXX: send ICMP error even if DF is not set. */
+ if (err == -EMSGSIZE) {
+ if (skb->protocol == htons(ETH_P_IP))
+ icmp_send(skb, ICMP_DEST_UNREACH,
+ ICMP_FRAG_NEEDED, htonl(mtu));
+ else
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ }
+
+ goto tx_err;
+ }
+ return NETDEV_TX_OK;
+
+tx_err:
+ stats = &t->dev->stats;
+ stats->tx_errors++;
+ stats->tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
{
struct net_device *dev = t->dev;
@@ -1111,7 +1237,6 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
dev_hold(dev);
}
-
static struct inet6_protocol ip6gre_protocol __read_mostly = {
.handler = gre_rcv,
.err_handler = ip6gre_err,
@@ -1126,7 +1251,8 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
for_each_netdev_safe(net, dev, aux)
if (dev->rtnl_link_ops == &ip6gre_link_ops ||
- dev->rtnl_link_ops == &ip6gre_tap_ops)
+ dev->rtnl_link_ops == &ip6gre_tap_ops ||
+ dev->rtnl_link_ops == &ip6erspan_tap_ops)
unregister_netdevice_queue(dev, head);
for (prio = 0; prio < 4; prio++) {
@@ -1248,6 +1374,47 @@ static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
return ip6gre_tunnel_validate(tb, data, extack);
}
+static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ __be16 flags = 0;
+ int ret;
+
+ if (!data)
+ return 0;
+
+ ret = ip6gre_tap_validate(tb, data, extack);
+ if (ret)
+ return ret;
+
+ /* ERSPAN should only have GRE sequence and key flag */
+ if (data[IFLA_GRE_OFLAGS])
+ flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
+ if (data[IFLA_GRE_IFLAGS])
+ flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
+ if (!data[IFLA_GRE_COLLECT_METADATA] &&
+ flags != (GRE_SEQ | GRE_KEY))
+ return -EINVAL;
+
+ /* ERSPAN Session ID only has 10-bit. Since we reuse
+ * 32-bit key field as ID, check it's range.
+ */
+ if (data[IFLA_GRE_IKEY] &&
+ (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
+ return -EINVAL;
+
+ if (data[IFLA_GRE_OKEY] &&
+ (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
+ return -EINVAL;
+
+ if (data[IFLA_GRE_ERSPAN_INDEX]) {
+ u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+
+ if (index & ~INDEX_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
static void ip6gre_netlink_parms(struct nlattr *data[],
struct __ip6_tnl_parm *parms)
@@ -1294,6 +1461,9 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
if (data[IFLA_GRE_FWMARK])
parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
+
+ if (data[IFLA_GRE_ERSPAN_INDEX])
+ parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
}
static int ip6gre_tap_init(struct net_device *dev)
@@ -1330,6 +1500,59 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
NETIF_F_HIGHDMA | \
NETIF_F_HW_CSUM)
+static int ip6erspan_tap_init(struct net_device *dev)
+{
+ struct ip6_tnl *tunnel;
+ int t_hlen;
+ int ret;
+
+ tunnel = netdev_priv(dev);
+
+ tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
+ strcpy(tunnel->parms.name, dev->name);
+
+ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!dev->tstats)
+ return -ENOMEM;
+
+ ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+ if (ret) {
+ free_percpu(dev->tstats);
+ dev->tstats = NULL;
+ return ret;
+ }
+
+ tunnel->tun_hlen = 8;
+ tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
+ sizeof(struct erspanhdr);
+ t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
+
+ dev->hard_header_len = LL_MAX_HEADER + t_hlen;
+ dev->mtu = ETH_DATA_LEN - t_hlen;
+ if (dev->type == ARPHRD_ETHER)
+ dev->mtu -= ETH_HLEN;
+ if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+ dev->mtu -= 8;
+
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ tunnel = netdev_priv(dev);
+ ip6gre_tnl_link_config(tunnel, 1);
+
+ return 0;
+}
+
+static const struct net_device_ops ip6erspan_netdev_ops = {
+ .ndo_init = ip6erspan_tap_init,
+ .ndo_uninit = ip6gre_tunnel_uninit,
+ .ndo_start_xmit = ip6erspan_tunnel_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = ip6_tnl_change_mtu,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_get_iflink = ip6_tnl_get_iflink,
+};
+
static void ip6gre_tap_setup(struct net_device *dev)
{
@@ -1521,6 +1744,8 @@ static size_t ip6gre_get_size(const struct net_device *dev)
nla_total_size(2) +
/* IFLA_GRE_FWMARK */
nla_total_size(4) +
+ /* IFLA_GRE_ERSPAN_INDEX */
+ nla_total_size(4) +
0;
}
@@ -1542,7 +1767,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) ||
nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) ||
- nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark))
+ nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) ||
+ nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
goto nla_put_failure;
if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
@@ -1578,8 +1804,23 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
[IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
[IFLA_GRE_FWMARK] = { .type = NLA_U32 },
+ [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 },
};
+static void ip6erspan_tap_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+
+ dev->netdev_ops = &ip6erspan_netdev_ops;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = ip6gre_dev_free;
+
+ dev->features |= NETIF_F_NETNS_LOCAL;
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ netif_keep_dst(dev);
+}
+
static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
.kind = "ip6gre",
.maxtype = IFLA_GRE_MAX,
@@ -1609,6 +1850,20 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
.get_link_net = ip6_tnl_get_link_net,
};
+static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = {
+ .kind = "ip6erspan",
+ .maxtype = IFLA_GRE_MAX,
+ .policy = ip6gre_policy,
+ .priv_size = sizeof(struct ip6_tnl),
+ .setup = ip6erspan_tap_setup,
+ .validate = ip6erspan_tap_validate,
+ .newlink = ip6gre_newlink,
+ .changelink = ip6gre_changelink,
+ .get_size = ip6gre_get_size,
+ .fill_info = ip6gre_fill_info,
+ .get_link_net = ip6_tnl_get_link_net,
+};
+
/*
* And now the modules code and kernel interface.
*/
@@ -1637,9 +1892,15 @@ static int __init ip6gre_init(void)
if (err < 0)
goto tap_ops_failed;
+ err = rtnl_link_register(&ip6erspan_tap_ops);
+ if (err < 0)
+ goto erspan_link_failed;
+
out:
return err;
+erspan_link_failed:
+ rtnl_link_unregister(&ip6gre_tap_ops);
tap_ops_failed:
rtnl_link_unregister(&ip6gre_link_ops);
rtnl_link_failed:
@@ -1653,6 +1914,7 @@ static void __exit ip6gre_fini(void)
{
rtnl_link_unregister(&ip6gre_tap_ops);
rtnl_link_unregister(&ip6gre_link_ops);
+ rtnl_link_unregister(&ip6erspan_tap_ops);
inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE);
unregister_pernet_device(&ip6gre_net_ops);
}
--
2.7.4
^ permalink raw reply related
* Fw: [Bug 198047] New: Regression in e1000e with kernel 4.14.3
From: Stephen Hemminger @ 2017-11-30 19:53 UTC (permalink / raw)
To: netdev, intel-wired-lan
Begin forwarded message:
Date: Thu, 30 Nov 2017 19:32:04 +0000
From: bugzilla-daemon@bugzilla.kernel.org
To: stephen@networkplumber.org
Subject: [Bug 198047] New: Regression in e1000e with kernel 4.14.3
https://bugzilla.kernel.org/show_bug.cgi?id=198047
Bug ID: 198047
Summary: Regression in e1000e with kernel 4.14.3
Product: Networking
Version: 2.5
Kernel Version: 4.14.3
Hardware: x86-64
OS: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Other
Assignee: stephen@networkplumber.org
Reporter: rwarsow@gmx.de
Regression: No
Created attachment 260963
--> https://bugzilla.kernel.org/attachment.cgi?id=260963&action=edit
screenshot network manager
I got a regression with my network interface e1000e.
With kernel 4.14.3 and Fedora 27 the network interface e1000e doesn't come up
if I set MTU to 1492 and boot with that settings.
with MTU set to auto sometimes the interface is active and sometimes not.
In network manager (Fedora 27) the button to activate/deactivate the network
interface is greyed out. Computers backside network LED'S are off.
there are no errors in the logs nor selinux issues, ...
up to 4.13.2 all kernels from 4.13 series I got no errors.
how can I debug this ?
Maybe from interest:
with the late Fedora 27 Beta (I believe kernel 4.12.x) I remember issues
switching interface MTU from auto to 1492.
lspci:
=====
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (2) I219-V
Subsystem: Micro-Star International Co., Ltd. [MSI] Device 7a72
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr-
Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort-
<MAbort- >SERR- <PERR- INTx-
Interrupt: pin A routed to IRQ 123
Region 0: Memory at df100000 (32-bit, non-prefetchable) [disabled]
[size=128K]
Capabilities: <access denied>
Kernel driver in use: e1000e
dmesg | grep -iE 'eth|enp0s31f6':
================================
[ 1.255886] e1000e 0000:00:1f.6 eth0: (PCI Express:2.5GT/s:Width x1)
4c:cc:6a:bc:8c:a2
[ 1.255889] e1000e 0000:00:1f.6 eth0: Intel(R) PRO/1000 Network Connection
[ 1.256032] e1000e 0000:00:1f.6 eth0: MAC: 12, PHY: 12, PBA No: FFFFFF-0FF
[ 1.495646] e1000e 0000:00:1f.6 enp0s31f6: renamed from eth0
[ 4.091853] e1000e 0000:00:1f.6 enp0s31f6: changing MTU from 1500 to 1492
[ 4.250990] IPv6: ADDRCONF(NETDEV_UP): enp0s31f6: link is not ready
[ 4.463180] IPv6: ADDRCONF(NETDEV_UP): enp0s31f6: link is not ready
nmcli connection show:
=====================
NAME UUID TYPE DEVICE
Profile 1 0e0cc197-be48-43a7-83d8-423ee89a448e 802-3-ethernet --
--
You are receiving this mail because:
You are the assignee for the bug.
^ permalink raw reply
* [PATCH net-next 0/5] PHYLINK preparatory patches for DSA
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
Hi all,
In preparation for having DSA migrate to PHYLINK, I had to come up with a
number of preparatory patches:
- we need to be able to pass phy_flags from an external component calling
phylink_of_phy_connect()
- DSA tries to connect through OF first, then fallsback using its own internal
MDIO bus, in that case we would both show an error, but also not know what
the correct phy_interface_t would be, instead use the PHY device/driver provided
one
- Finally bcm_sf2 makes use of all possible PHYs out there: internal, external,
fixed, and MoCA, the latter requires a bit of help to signal link notifications
through a MMIO interrupt, as well a report a correct PORT type
Florian Fainelli (5):
net: phy: phylink: Allow specifying PHY device flags
net: phy: phylink: Use PHY device interface if N/A
net: phy: phylink: Demote error message to debug
net: phy: phylink: Allow setting a custom link state callback
net: phy: phylink: Report MoCA as PORT_BNC
drivers/net/phy/phylink.c | 45 +++++++++++++++++++++++++++++++++++++++------
include/linux/phylink.h | 5 ++++-
2 files changed, 43 insertions(+), 7 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH net-next 1/5] net: phy: phylink: Allow specifying PHY device flags
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
In-Reply-To: <20171130195744.17743-1-f.fainelli@gmail.com>
In order to let subsystems like DSA fully utilize PHYLINK, we need to be able
to communicate phy_device::flags from of_phy_{connect,attach} even when using
PHYLINK APIs.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 6 ++++--
include/linux/phylink.h | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index e3bbc70372d3..0a81c7ff51b5 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -669,7 +669,8 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
}
EXPORT_SYMBOL_GPL(phylink_connect_phy);
-int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
+int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
+ u32 flags)
{
struct device_node *phy_node;
struct phy_device *phy_dev;
@@ -693,7 +694,8 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
return 0;
}
- phy_dev = of_phy_attach(pl->netdev, phy_node, 0, pl->link_interface);
+ phy_dev = of_phy_attach(pl->netdev, phy_node, flags,
+ pl->link_interface);
/* We're done with the phy_node handle */
of_node_put(phy_node);
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index af67edd4ae38..875717a4e873 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -105,7 +105,7 @@ struct phylink *phylink_create(struct net_device *, struct device_node *,
void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *);
-int phylink_of_phy_connect(struct phylink *, struct device_node *);
+int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
void phylink_disconnect_phy(struct phylink *);
void phylink_mac_change(struct phylink *, bool up);
--
2.14.3
^ permalink raw reply related
* [PATCH net-next 2/5] net: phy: phylink: Use PHY device interface if N/A
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
In-Reply-To: <20171130195744.17743-1-f.fainelli@gmail.com>
We may not always be able to resolve a correct phy_interface_t value before
actually connecting to the PHY device, when that happens, just have
phylink_connect_phy() utilize what the PHY device/driver provided.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0a81c7ff51b5..8a30ea8873af 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -657,6 +657,12 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
{
int ret;
+ /* Use PHY device/driver interface */
+ if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
+ pl->link_interface = phy->interface;
+ pl->link_config.interface = pl->link_interface;
+ }
+
ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface);
if (ret)
return ret;
--
2.14.3
^ permalink raw reply related
* [PATCH net-next 3/5] net: phy: phylink: Demote error message to debug
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
In-Reply-To: <20171130195744.17743-1-f.fainelli@gmail.com>
Some subsystems like DSA may be trying to connect to a PHY through OF first,
and then attempt a connect using a local MDIO bus, demote the error message:
"unable to find PHY node" into a debug print.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 8a30ea8873af..a41f0a224512 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -694,7 +694,7 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
if (!phy_node) {
if (pl->link_an_mode == MLO_AN_PHY) {
- netdev_err(pl->netdev, "unable to find PHY node\n");
+ netdev_dbg(pl->netdev, "unable to find PHY node\n");
return -ENODEV;
}
return 0;
--
2.14.3
^ permalink raw reply related
* [PATCH net-next 4/5] net: phy: phylink: Allow setting a custom link state callback
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
In-Reply-To: <20171130195744.17743-1-f.fainelli@gmail.com>
phylink_get_fixed_state() currently consults an optional "link_gpio"
GPIO descriptor, expand this mechanism to allow specifying a custom
callback. This is necessary to support out of band link notifcation
(e.g: from an interrupt within a MMIO register).
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 26 ++++++++++++++++++++++++--
include/linux/phylink.h | 3 +++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a41f0a224512..0a8fd9aa1a19 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -50,6 +50,8 @@ struct phylink {
/* The link configuration settings */
struct phylink_link_state link_config;
struct gpio_desc *link_gpio;
+ void (*get_fixed_state)(struct net_device *dev,
+ struct phylink_link_state *s);
struct mutex state_mutex;
struct phylink_link_state phy_state;
@@ -339,12 +341,14 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *
}
/* The fixed state is... fixed except for the link state,
- * which may be determined by a GPIO.
+ * which may be determined by a GPIO or a callback.
*/
static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state)
{
*state = pl->link_config;
- if (pl->link_gpio)
+ if (pl->get_fixed_state)
+ pl->get_fixed_state(pl->netdev, state);
+ else if (pl->link_gpio)
state->link = !!gpiod_get_value(pl->link_gpio);
}
@@ -737,6 +741,24 @@ void phylink_disconnect_phy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
+int phylink_fixed_state_cb(struct phylink *pl,
+ void (*cb)(struct net_device *dev,
+ struct phylink_link_state *state))
+{
+ /* It does not make sense to let the link be overriden unless we use
+ * MLO_AN_FIXED
+ */
+ if (pl->link_an_mode != MLO_AN_FIXED)
+ return -EINVAL;
+
+ mutex_lock(&pl->state_mutex);
+ pl->get_fixed_state = cb;
+ mutex_unlock(&pl->state_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(phylink_fixed_state_cb);
+
void phylink_mac_change(struct phylink *pl, bool up)
{
if (!up)
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 875717a4e873..d505ea321eb5 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -107,6 +107,9 @@ void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
void phylink_disconnect_phy(struct phylink *);
+int phylink_fixed_state_cb(struct phylink *,
+ void (*cb)(struct net_device *dev,
+ struct phylink_link_state *));
void phylink_mac_change(struct phylink *, bool up);
--
2.14.3
^ permalink raw reply related
* [PATCH net-next 5/5] net: phy: phylink: Report MoCA as PORT_BNC
From: Florian Fainelli @ 2017-11-30 19:57 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, rmk+kernel, vivien.didelot, Florian Fainelli
In-Reply-To: <20171130195744.17743-1-f.fainelli@gmail.com>
Similarly to what PHYLIB already does, make sure that
PHY_INTERFACE_MODE_MOCA is reported as PORT_BNC.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0a8fd9aa1a19..20c48fbebdfb 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -525,7 +525,10 @@ struct phylink *phylink_create(struct net_device *ndev, struct device_node *np,
pl->netdev = ndev;
pl->phy_state.interface = iface;
pl->link_interface = iface;
- pl->link_port = PORT_MII;
+ if (iface == PHY_INTERFACE_MODE_MOCA)
+ pl->link_port = PORT_BNC;
+ else
+ pl->link_port = PORT_MII;
pl->link_config.interface = iface;
pl->link_config.pause = MLO_PAUSE_AN;
pl->link_config.speed = SPEED_UNKNOWN;
--
2.14.3
^ permalink raw reply related
* Re: [PATCH net-next] net: llc: remove init_net check
From: Eric Dumazet @ 2017-11-30 20:12 UTC (permalink / raw)
To: Alexander Aring, davem; +Cc: hadi, netdev
In-Reply-To: <20171130194526.8076-1-aring@mojatatu.com>
On Thu, 2017-11-30 at 14:45 -0500, Alexander Aring wrote:
> Commit e730c15519d09 ("[NET]: Make packet reception network namespace
> safe") added several init_net compares to protocols with unknown
> net namespace support. The idea was as users started using the
> different
> protocols they would test and enable them.
> In our use-case we generate STP enabled Linux bridges in different
> namespaces. The bridges are connected via veth interfaces.
> This patch makes STP work in such a setup.
>
> Signed-off-by: Alexander Aring <aring@mojatatu.com>
> ---
> net/llc/llc_input.c | 4 ----
> 1 file changed, 4 deletions(-)
>
> diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
> index 82cb93f66b9b..09b530d90610 100644
> --- a/net/llc/llc_input.c
> +++ b/net/llc/llc_input.c
> @@ -14,7 +14,6 @@
> #include <linux/netdevice.h>
> #include <linux/slab.h>
> #include <linux/export.h>
> -#include <net/net_namespace.h>
> #include <net/llc.h>
> #include <net/llc_pdu.h>
> #include <net/llc_sap.h>
> @@ -162,9 +161,6 @@ int llc_rcv(struct sk_buff *skb, struct
> net_device *dev,
> void (*sta_handler)(struct sk_buff *skb);
> void (*sap_handler)(struct llc_sap *sap, struct sk_buff
> *skb);
>
> - if (!net_eq(dev_net(dev), &init_net))
> - goto drop;
> -
> /*
> * When the interface is in promisc. mode, drop all the crap
> that it
> * receives, do not try to analyse it.
Well, we use different netns for isolation.
You need more changes than simply removing this check, I guess.
__llc_sap_find() would need a per netns list, or proper netns checks.
^ permalink raw reply
* Re: [PATCH v7 1/5] add infrastructure for tagging functions as error injectable
From: Josef Bacik @ 2017-11-30 20:15 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Josef Bacik, Jonathan Corbet, rostedt, mingo, davem, netdev,
linux-kernel, ast, kernel-team, linux-btrfs, Josef Bacik
In-Reply-To: <83414bdd-2e83-bc77-da90-33ee43b89a97@iogearbox.net>
On Wed, Nov 29, 2017 at 05:59:39PM +0100, Daniel Borkmann wrote:
> On 11/28/2017 09:02 PM, Josef Bacik wrote:
> > On Tue, Nov 28, 2017 at 11:58:41AM -0700, Jonathan Corbet wrote:
> >> On Wed, 22 Nov 2017 16:23:30 -0500
> >> Josef Bacik <josef@toxicpanda.com> wrote:
> >>> From: Josef Bacik <jbacik@fb.com>
> >>>
> >>> Using BPF we can override kprob'ed functions and return arbitrary
> >>> values. Obviously this can be a bit unsafe, so make this feature opt-in
> >>> for functions. Simply tag a function with KPROBE_ERROR_INJECT_SYMBOL in
> >>> order to give BPF access to that function for error injection purposes.
> >>>
> >>> Signed-off-by: Josef Bacik <jbacik@fb.com>
> >>> Acked-by: Ingo Molnar <mingo@kernel.org>
> >>> ---
> >>> arch/x86/include/asm/asm.h | 6 ++
> >>> include/asm-generic/vmlinux.lds.h | 10 +++
> >>> include/linux/bpf.h | 11 +++
> >>> include/linux/kprobes.h | 1 +
> >>> include/linux/module.h | 5 ++
> >>> kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++
> >>> kernel/module.c | 6 +-
> >>> 7 files changed, 201 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
> >>> index b0dc91f4bedc..340f4cc43255 100644
> >>> --- a/arch/x86/include/asm/asm.h
> >>> +++ b/arch/x86/include/asm/asm.h
> >>> @@ -85,6 +85,12 @@
> >>> _ASM_PTR (entry); \
> >>> .popsection
> >>>
> >>> +# define _ASM_KPROBE_ERROR_INJECT(entry) \
> >>> + .pushsection "_kprobe_error_inject_list","aw" ; \
> >>> + _ASM_ALIGN ; \
> >>> + _ASM_PTR (entry); \
> >>> + .popseciton
> >>
> >> So this stuff is not my area of greatest expertise, but I do have to wonder
> >> how ".popseciton" can work ... ?
> >
> > Well fuck, do you want me to send a increment Daniel/Alexei or resend this patch
> > fixed? Thanks,
>
> Sorry for late reply, please rebase + respin the whole series with
> this fixed. There were also few typos in the cover letter / commit
> messages that would be good to get fixed along the way.
>
> Also, could you debug why this wasn't caught at compile/runtime during
> testing?
>
Sat down to figure out what was wrong here, and realized I'm just an idiot. I
was copying the no kprobe stuff, and my grepping did not uncover what
_ASM_NOKPROBE() was used for, so I assumed it was some auto generated magic and
just copied what it did to cover my bases. Sat down to figure it out and it is
actually called in some assembly files (which is why cscope didn't find it). So
we don't need _ASM_KPROBE_ERROR_INJECT at all. I'll drop it and respin and send
it along. Thanks,
Josef
^ permalink raw reply
* Re: [PATCH net-next 1/3] rds: tcp: remove redundant function rds_tcp_conn_paths_destroy()
From: Santosh Shilimkar @ 2017-11-30 20:20 UTC (permalink / raw)
To: Sowmini Varadhan, netdev; +Cc: davem, rds-devel
In-Reply-To: <01449f728c031e98e370ac78e6a7d714aec8cfca.1511195030.git.sowmini.varadhan@oracle.com>
On 11/30/2017 11:11 AM, Sowmini Varadhan wrote:
> A side-effect of Commit c14b0366813a ("rds: tcp: set linger to 1
> when unloading a rds-tcp") is that we always send a RST on the tcp
> connection for rds_conn_destroy(), so rds_tcp_conn_paths_destroy()
> is not needed any more and is removed in this patch.
>
> Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
> ---
Looks good.
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
^ 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