* [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP
@ 2016-07-06 18:22 Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-06 18:22 UTC (permalink / raw)
To: netdev
This short series provides support for MPLS in IPv4 (RFC4023), and by
virtue of FOU, MPLS in UDP (RFC7510).
The changes are as follows:
1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
AF_INET6
2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
SIT also already handles IPv6.
3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
A corresponding iproute2 patchset will also be posted.
Simon Horman (4):
tunnels: support MPLS over IPv4 tunnels
sit: support MPLS over IPv4
ipip: support MPLS over IPv4
mpls: allow routes on ipip and sit devices
net/ipv4/ipip.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++-------
net/ipv4/tunnel4.c | 77 ++++++++++++++++++++++++++----
net/ipv6/sit.c | 93 +++++++++++++++++++++++++++++-------
net/mpls/af_mpls.c | 6 ++-
4 files changed, 269 insertions(+), 44 deletions(-)
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH/RFC net-next 1/4] tunnels: support MPLS over IPv4 tunnels
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
@ 2016-07-06 18:22 ` Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4 Simon Horman
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-06 18:22 UTC (permalink / raw)
To: netdev
Extend tunnel support to MPLS over IPv4. The implementation extends the
existing differentiation between IPIP and IPv6 over IPv4 to also cover MPLS
over IPv4.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
net/ipv4/tunnel4.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 67 insertions(+), 10 deletions(-)
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d0171830620..45cd4253583a 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -6,6 +6,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/mpls.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
@@ -16,11 +17,14 @@
static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly;
static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly;
+static struct xfrm_tunnel __rcu *tunnelmpls4_handlers __read_mostly;
static DEFINE_MUTEX(tunnel4_mutex);
static inline struct xfrm_tunnel __rcu **fam_handlers(unsigned short family)
{
- return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+ return (family == AF_INET) ? &tunnel4_handlers :
+ (family == AF_INET6) ? &tunnel64_handlers :
+ &tunnelmpls4_handlers;
}
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
@@ -125,6 +129,26 @@ drop:
}
#endif
+#if IS_ENABLED(CONFIG_MPLS)
+static int tunnelmpls4_rcv(struct sk_buff *skb)
+{
+ struct xfrm_tunnel *handler;
+
+ if (!pskb_may_pull(skb, sizeof(struct mpls_label)))
+ goto drop;
+
+ for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+#endif
+
static void tunnel4_err(struct sk_buff *skb, u32 info)
{
struct xfrm_tunnel *handler;
@@ -145,6 +169,17 @@ static void tunnel64_err(struct sk_buff *skb, u32 info)
}
#endif
+#if IS_ENABLED(CONFIG_MPLS)
+static void tunnelmpls4_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm_tunnel *handler;
+
+ for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+#endif
+
static const struct net_protocol tunnel4_protocol = {
.handler = tunnel4_rcv,
.err_handler = tunnel4_err,
@@ -161,24 +196,46 @@ static const struct net_protocol tunnel64_protocol = {
};
#endif
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct net_protocol tunnelmpls4_protocol = {
+ .handler = tunnelmpls4_rcv,
+ .err_handler = tunnelmpls4_err,
+ .no_policy = 1,
+ .netns_ok = 1,
+};
+#endif
+
static int __init tunnel4_init(void)
{
- if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
- pr_err("%s: can't add protocol\n", __func__);
- return -EAGAIN;
- }
+ if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+ goto err_ipip;
#if IS_ENABLED(CONFIG_IPV6)
- if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
- pr_err("tunnel64 init: can't add protocol\n");
- inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
- return -EAGAIN;
- }
+ if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6))
+ goto err_ipv6;
+#endif
+#if IS_ENABLED(CONFIG_MPLS)
+ if (inet_add_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
+ goto err_mpls;
#endif
return 0;
+
+#if IS_ENABLED(CONFIG_IPV6)
+err_mpls:
+ inet_del_protocol(&tunnel4_protocol, IPPROTO_IPV6);
+#endif
+err_ipv6:
+ inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
+err_ipip:
+ pr_err("%s: can't add protocol\n", __func__);
+ return -EAGAIN;
}
static void __exit tunnel4_fini(void)
{
+#if IS_ENABLED(CONFIG_MPLS)
+ if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
+ pr_err("tunnelmpls4 close: can't remove protocol\n");
+#endif
#if IS_ENABLED(CONFIG_IPV6)
if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
pr_err("tunnel64 close: can't remove protocol\n");
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
@ 2016-07-06 18:22 ` Simon Horman
2016-07-07 5:10 ` David Miller
2016-07-06 18:22 ` [PATCH/RFC net-next 3/4] ipip: " Simon Horman
` (3 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Simon Horman @ 2016-07-06 18:22 UTC (permalink / raw)
To: netdev
Extend the SIT driver to support MPLS over IPv4. This implementation
extends existing support for IPv6 over IPv4 and IPv4 over IPv4.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
net/ipv6/sit.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 77 insertions(+), 16 deletions(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 917a5cd4b8fc..5d96a09102c7 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -688,12 +688,19 @@ out:
return 0;
}
-static const struct tnl_ptk_info tpi = {
+static const struct tnl_ptk_info ipip_tpi = {
/* no tunnel info required for ipip. */
.proto = htons(ETH_P_IP),
};
-static int ipip_rcv(struct sk_buff *skb)
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct tnl_ptk_info mplsip_tpi = {
+ /* no tunnel info required for mplsip. */
+ .proto = htons(ETH_P_MPLS_UC),
+};
+#endif
+
+static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
{
const struct iphdr *iph;
struct ip_tunnel *tunnel;
@@ -702,15 +709,23 @@ static int ipip_rcv(struct sk_buff *skb)
tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
iph->saddr, iph->daddr);
if (tunnel) {
- if (tunnel->parms.iph.protocol != IPPROTO_IPIP &&
+ const struct tnl_ptk_info *tpi;
+
+ if (tunnel->parms.iph.protocol != ipproto &&
tunnel->parms.iph.protocol != 0)
goto drop;
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto drop;
- if (iptunnel_pull_header(skb, 0, tpi.proto, false))
+#if IS_ENABLED(CONFIG_MPLS)
+ if (ipproto == IPPROTO_MPLS)
+ tpi = &mplsip_tpi;
+ else
+#endif
+ tpi = &ipip_tpi;
+ if (iptunnel_pull_header(skb, 0, tpi->proto, false))
goto drop;
- return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, log_ecn_error);
+ return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
}
return 1;
@@ -720,6 +735,18 @@ drop:
return 0;
}
+static int ipip_rcv(struct sk_buff *skb)
+{
+ return sit_tunnel_rcv(skb, IPPROTO_IPIP);
+}
+
+#if IS_ENABLED(CONFIG_MPLS)
+static int mplsip_rcv(struct sk_buff *skb)
+{
+ return sit_tunnel_rcv(skb, IPPROTO_MPLS);
+}
+#endif
+
/*
* If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
* stores the embedded IPv4 address in v4dst and returns true.
@@ -958,7 +985,8 @@ tx_error:
return NETDEV_TX_OK;
}
-static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
+ struct net_device *dev, u8 ipproto)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
const struct iphdr *tiph = &tunnel->parms.iph;
@@ -966,9 +994,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
goto tx_error;
- skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+ skb_set_inner_ipproto(skb, ipproto);
- ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP);
+ ip_tunnel_xmit(skb, dev, tiph, ipproto);
return NETDEV_TX_OK;
tx_error:
kfree_skb(skb);
@@ -981,11 +1009,16 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
{
switch (skb->protocol) {
case htons(ETH_P_IP):
- ipip_tunnel_xmit(skb, dev);
+ sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP);
break;
case htons(ETH_P_IPV6):
ipip6_tunnel_xmit(skb, dev);
break;
+#if IS_ENABLED(CONFIG_MPLS)
+ case htons(ETH_P_MPLS_UC):
+ sit_tunnel_xmit__(skb, dev, IPPROTO_MPLS);
+ break;
+#endif
default:
goto tx_err;
}
@@ -1093,6 +1126,16 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
}
#endif
+bool ipip6_valid_ip_proto(u8 ipproto)
+{
+ return ipproto == IPPROTO_IPV6 ||
+ ipproto != IPPROTO_IPIP ||
+#if IS_ENABLED(CONFIG_MPLS)
+ ipproto == IPPROTO_MPLS ||
+#endif
+ ipproto == 0;
+}
+
static int
ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -1152,9 +1195,7 @@ ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
goto done;
err = -EINVAL;
- if (p.iph.protocol != IPPROTO_IPV6 &&
- p.iph.protocol != IPPROTO_IPIP &&
- p.iph.protocol != 0)
+ if (!ipip6_valid_ip_proto(p.iph.protocol))
goto done;
if (p.iph.version != 4 ||
p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
@@ -1379,9 +1420,7 @@ static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
- if (proto != IPPROTO_IPV6 &&
- proto != IPPROTO_IPIP &&
- proto != 0)
+ if (!ipip6_valid_ip_proto(proto))
return -EINVAL;
return 0;
@@ -1723,6 +1762,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
.priority = 2,
};
+#if IS_ENABLED(CONFIG_MPLS)
+static struct xfrm_tunnel mplsip_handler __read_mostly = {
+ .handler = mplsip_rcv,
+ .err_handler = ipip6_err,
+ .priority = 2,
+};
+#endif
+
static void __net_exit sit_destroy_tunnels(struct net *net,
struct list_head *head)
{
@@ -1818,6 +1865,9 @@ static void __exit sit_cleanup(void)
rtnl_link_unregister(&sit_link_ops);
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+#if IS_ENABLED(CONFIG_MPLS)
+ xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
+#endif
unregister_pernet_device(&sit_net_ops);
rcu_barrier(); /* Wait for completion of call_rcu()'s */
@@ -1827,7 +1877,7 @@ static int __init sit_init(void)
{
int err;
- pr_info("IPv6 over IPv4 tunneling driver\n");
+ pr_info("IPv6, IPv4 and MPLS over IPv4 tunneling driver\n");
err = register_pernet_device(&sit_net_ops);
if (err < 0)
@@ -1842,6 +1892,13 @@ static int __init sit_init(void)
pr_info("%s: can't register ip4ip4\n", __func__);
goto xfrm_tunnel4_failed;
}
+#if IS_ENABLED(CONFIG_MPLS)
+ err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
+ if (err < 0) {
+ pr_info("%s: can't register mplsip\n", __func__);
+ goto xfrm_tunnel_mpls_failed;
+ }
+#endif
err = rtnl_link_register(&sit_link_ops);
if (err < 0)
goto rtnl_link_failed;
@@ -1850,6 +1907,10 @@ out:
return err;
rtnl_link_failed:
+#if IS_ENABLED(CONFIG_MPLS)
+ xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
+xfrm_tunnel_mpls_failed:
+#endif
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
xfrm_tunnel4_failed:
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH/RFC net-next 3/4] ipip: support MPLS over IPv4
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4 Simon Horman
@ 2016-07-06 18:22 ` Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 4/4] mpls: allow routes on ipip and sit devices Simon Horman
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-06 18:22 UTC (permalink / raw)
To: netdev
Extend the IPIP driver to support MPLS over IPv4. The implementation is an
extension of existing support for IPv4 over IPv4 and is based of multiple
inner-protocol support for the SIT driver.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
net/ipv4/ipip.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 121 insertions(+), 16 deletions(-)
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 978370132f29..4ae3f8e6c6cc 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -148,14 +148,14 @@ static int ipip_err(struct sk_buff *skb, u32 info)
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
ipv4_update_pmtu(skb, dev_net(skb->dev), info,
- t->parms.link, 0, IPPROTO_IPIP, 0);
+ t->parms.link, 0, iph->protocol, 0);
err = 0;
goto out;
}
if (type == ICMP_REDIRECT) {
ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
- IPPROTO_IPIP, 0);
+ iph->protocol, 0);
err = 0;
goto out;
}
@@ -177,12 +177,19 @@ out:
return err;
}
-static const struct tnl_ptk_info tpi = {
+static const struct tnl_ptk_info ipip_tpi = {
/* no tunnel info required for ipip. */
.proto = htons(ETH_P_IP),
};
-static int ipip_rcv(struct sk_buff *skb)
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct tnl_ptk_info mplsip_tpi = {
+ /* no tunnel info required for mplsip. */
+ .proto = htons(ETH_P_MPLS_UC),
+};
+#endif
+
+static int ipip_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
{
struct net *net = dev_net(skb->dev);
struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
@@ -193,11 +200,23 @@ static int ipip_rcv(struct sk_buff *skb)
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
iph->saddr, iph->daddr, 0);
if (tunnel) {
+ const struct tnl_ptk_info *tpi;
+
+ if (tunnel->parms.iph.protocol != ipproto &&
+ tunnel->parms.iph.protocol != 0)
+ goto drop;
+
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto drop;
- if (iptunnel_pull_header(skb, 0, tpi.proto, false))
+#if IS_ENABLED(CONFIG_MPLS)
+ if (ipproto == IPPROTO_MPLS)
+ tpi = &mplsip_tpi;
+ else
+#endif
+ tpi = &ipip_tpi;
+ if (iptunnel_pull_header(skb, 0, tpi->proto, false))
goto drop;
- return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, log_ecn_error);
+ return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
}
return -1;
@@ -207,24 +226,51 @@ drop:
return 0;
}
+static int ipip_rcv(struct sk_buff *skb)
+{
+ return ipip_tunnel_rcv(skb, IPPROTO_IPIP);
+}
+
+#if IS_ENABLED(CONFIG_MPLS)
+static int mplsip_rcv(struct sk_buff *skb)
+{
+ return ipip_tunnel_rcv(skb, IPPROTO_MPLS);
+}
+#endif
+
/*
* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
*/
-static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
const struct iphdr *tiph = &tunnel->parms.iph;
+ u8 ipproto;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ ipproto = IPPROTO_IPIP;
+ break;
+#if IS_ENABLED(CONFIG_MPLS)
+ case htons(ETH_P_MPLS_UC):
+ ipproto = IPPROTO_MPLS;
+ break;
+#endif
+ default:
+ goto tx_error;
+ }
- if (unlikely(skb->protocol != htons(ETH_P_IP)))
+ if (tiph->protocol != ipproto && tiph->protocol != 0)
goto tx_error;
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
goto tx_error;
- skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+ skb_set_inner_ipproto(skb, ipproto);
- ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
+ ip_tunnel_xmit(skb, dev, tiph, ipproto);
return NETDEV_TX_OK;
tx_error:
@@ -234,6 +280,20 @@ tx_error:
return NETDEV_TX_OK;
}
+static bool ipip_tunnel_ioctl_verify_protocol(u8 ipproto)
+{
+ switch (ipproto) {
+ case 0:
+ case IPPROTO_IPIP:
+#if IS_ENABLED(CONFIG_MPLS)
+ case IPPROTO_MPLS:
+#endif
+ return true;
+ }
+
+ return false;
+}
+
static int
ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -244,7 +304,8 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EFAULT;
if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
- if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
+ if (p.iph.version != 4 ||
+ !ipip_tunnel_ioctl_verify_protocol(p.iph.protocol) ||
p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
return -EINVAL;
}
@@ -301,10 +362,23 @@ static int ipip_tunnel_init(struct net_device *dev)
tunnel->tun_hlen = 0;
tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
- tunnel->parms.iph.protocol = IPPROTO_IPIP;
return ip_tunnel_init(dev);
}
+static int ipip_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ u8 proto;
+
+ if (!data || !data[IFLA_IPTUN_PROTO])
+ return 0;
+
+ proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+ if (proto != IPPROTO_IPIP && proto != IPPROTO_MPLS && proto != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
static void ipip_netlink_parms(struct nlattr *data[],
struct ip_tunnel_parm *parms)
{
@@ -335,6 +409,9 @@ static void ipip_netlink_parms(struct nlattr *data[],
if (data[IFLA_IPTUN_TOS])
parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
+ if (data[IFLA_IPTUN_PROTO])
+ parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+
if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
parms->iph.frag_off = htons(IP_DF);
}
@@ -427,6 +504,8 @@ static size_t ipip_get_size(const struct net_device *dev)
nla_total_size(1) +
/* IFLA_IPTUN_TOS */
nla_total_size(1) +
+ /* IFLA_IPTUN_PROTO */
+ nla_total_size(1) +
/* IFLA_IPTUN_PMTUDISC */
nla_total_size(1) +
/* IFLA_IPTUN_ENCAP_TYPE */
@@ -450,6 +529,7 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_in_addr(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+ nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
!!(parm->iph.frag_off & htons(IP_DF))))
goto nla_put_failure;
@@ -476,6 +556,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
[IFLA_IPTUN_TTL] = { .type = NLA_U8 },
[IFLA_IPTUN_TOS] = { .type = NLA_U8 },
+ [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
[IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
[IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 },
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
@@ -489,6 +570,7 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly = {
.policy = ipip_policy,
.priv_size = sizeof(struct ip_tunnel),
.setup = ipip_tunnel_setup,
+ .validate = ipip_tunnel_validate,
.newlink = ipip_newlink,
.changelink = ipip_changelink,
.dellink = ip_tunnel_dellink,
@@ -503,6 +585,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
.priority = 1,
};
+#if IS_ENABLED(CONFIG_MPLS)
+static struct xfrm_tunnel mplsip_handler __read_mostly = {
+ .handler = mplsip_rcv,
+ .err_handler = ipip_err,
+ .priority = 1,
+};
+#endif
+
static int __net_init ipip_init_net(struct net *net)
{
return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
@@ -525,7 +615,7 @@ static int __init ipip_init(void)
{
int err;
- pr_info("ipip: IPv4 over IPv4 tunneling driver\n");
+ pr_info("ipip: IPv4 and MPLS over IPv4 tunneling driver\n");
err = register_pernet_device(&ipip_net_ops);
if (err < 0)
@@ -533,8 +623,15 @@ static int __init ipip_init(void)
err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
if (err < 0) {
pr_info("%s: can't register tunnel\n", __func__);
- goto xfrm_tunnel_failed;
+ goto xfrm_tunnel_ipip_failed;
+ }
+#if IS_ENABLED(CONFIG_MPLS)
+ err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
+ if (err < 0) {
+ pr_info("%s: can't register tunnel\n", __func__);
+ goto xfrm_tunnel_mplsip_failed;
}
+#endif
err = rtnl_link_register(&ipip_link_ops);
if (err < 0)
goto rtnl_link_failed;
@@ -543,8 +640,13 @@ out:
return err;
rtnl_link_failed:
+#if IS_ENABLED(CONFIG_MPLS)
+ xfrm4_tunnel_deregister(&mplsip_handler, AF_INET);
+xfrm_tunnel_mplsip_failed:
+
+#endif
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
-xfrm_tunnel_failed:
+xfrm_tunnel_ipip_failed:
unregister_pernet_device(&ipip_net_ops);
goto out;
}
@@ -554,7 +656,10 @@ static void __exit ipip_fini(void)
rtnl_link_unregister(&ipip_link_ops);
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
pr_info("%s: can't deregister tunnel\n", __func__);
-
+#if IS_ENABLED(CONFIG_MPLS)
+ if (xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS))
+ pr_info("%s: can't deregister tunnel\n", __func__);
+#endif
unregister_pernet_device(&ipip_net_ops);
}
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH/RFC net-next 4/4] mpls: allow routes on ipip and sit devices
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
` (2 preceding siblings ...)
2016-07-06 18:22 ` [PATCH/RFC net-next 3/4] ipip: " Simon Horman
@ 2016-07-06 18:22 ` Simon Horman
2016-07-07 4:44 ` [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Tom Herbert
2016-07-07 5:12 ` David Miller
5 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-06 18:22 UTC (permalink / raw)
To: netdev
Allow MPLS routes on IPIP and SIT devices now that they
support forwarding MPLS packets.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
net/mpls/af_mpls.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index e9beaa58573c..5c161e7759b5 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1009,10 +1009,12 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
unsigned int flags;
if (event == NETDEV_REGISTER) {
- /* For now just support Ethernet and IPGRE devices */
+ /* For now just support Ethernet, IPGRE, SIT and IPIP devices */
if (dev->type == ARPHRD_ETHER ||
dev->type == ARPHRD_LOOPBACK ||
- dev->type == ARPHRD_IPGRE) {
+ dev->type == ARPHRD_IPGRE ||
+ dev->type == ARPHRD_SIT ||
+ dev->type == ARPHRD_TUNNEL) {
mdev = mpls_add_dev(dev);
if (IS_ERR(mdev))
return notifier_from_errno(PTR_ERR(mdev));
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
` (3 preceding siblings ...)
2016-07-06 18:22 ` [PATCH/RFC net-next 4/4] mpls: allow routes on ipip and sit devices Simon Horman
@ 2016-07-07 4:44 ` Tom Herbert
2016-07-07 5:38 ` Simon Horman
2016-07-07 5:12 ` David Miller
5 siblings, 1 reply; 10+ messages in thread
From: Tom Herbert @ 2016-07-07 4:44 UTC (permalink / raw)
To: Simon Horman; +Cc: Linux Kernel Network Developers
On Wed, Jul 6, 2016 at 11:22 AM, Simon Horman
<simon.horman@netronome.com> wrote:
> This short series provides support for MPLS in IPv4 (RFC4023), and by
> virtue of FOU, MPLS in UDP (RFC7510).
>
> The changes are as follows:
> 1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
> AF_INET6
> 2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
> SIT also already handles IPv6.
> 3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
>
HI Siomon,
Thanks for these patches! Can provide the commands for testing this?
Tom
> A corresponding iproute2 patchset will also be posted.
>
> Simon Horman (4):
> tunnels: support MPLS over IPv4 tunnels
> sit: support MPLS over IPv4
> ipip: support MPLS over IPv4
> mpls: allow routes on ipip and sit devices
>
> net/ipv4/ipip.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++-------
> net/ipv4/tunnel4.c | 77 ++++++++++++++++++++++++++----
> net/ipv6/sit.c | 93 +++++++++++++++++++++++++++++-------
> net/mpls/af_mpls.c | 6 ++-
> 4 files changed, 269 insertions(+), 44 deletions(-)
>
> --
> 2.7.0.rc3.207.g0ac5344
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4
2016-07-06 18:22 ` [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4 Simon Horman
@ 2016-07-07 5:10 ` David Miller
2016-07-07 5:37 ` Simon Horman
0 siblings, 1 reply; 10+ messages in thread
From: David Miller @ 2016-07-07 5:10 UTC (permalink / raw)
To: simon.horman; +Cc: netdev
From: Simon Horman <simon.horman@netronome.com>
Date: Wed, 6 Jul 2016 20:22:33 +0200
>
> +bool ipip6_valid_ip_proto(u8 ipproto)
> +{
> + return ipproto == IPPROTO_IPV6 ||
> + ipproto != IPPROTO_IPIP ||
> +#if IS_ENABLED(CONFIG_MPLS)
> + ipproto == IPPROTO_MPLS ||
> +#endif
> + ipproto == 0;
> +}
This returns true any time ipproto is not equal to IPPROTO_IPIP,
which is probably not what you intended here.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
` (4 preceding siblings ...)
2016-07-07 4:44 ` [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Tom Herbert
@ 2016-07-07 5:12 ` David Miller
5 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2016-07-07 5:12 UTC (permalink / raw)
To: simon.horman; +Cc: netdev
From: Simon Horman <simon.horman@netronome.com>
Date: Wed, 6 Jul 2016 20:22:31 +0200
> This short series provides support for MPLS in IPv4 (RFC4023), and by
> virtue of FOU, MPLS in UDP (RFC7510).
>
> The changes are as follows:
> 1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
> AF_INET6
> 2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
> SIT also already handles IPv6.
> 3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
>
> A corresponding iproute2 patchset will also be posted.
Other than the protocol value test logic problem in patch #2, this looks
fine to me.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4
2016-07-07 5:10 ` David Miller
@ 2016-07-07 5:37 ` Simon Horman
0 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-07 5:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Wed, Jul 06, 2016 at 10:10:59PM -0700, David Miller wrote:
> From: Simon Horman <simon.horman@netronome.com>
> Date: Wed, 6 Jul 2016 20:22:33 +0200
>
> >
> > +bool ipip6_valid_ip_proto(u8 ipproto)
> > +{
> > + return ipproto == IPPROTO_IPV6 ||
> > + ipproto != IPPROTO_IPIP ||
> > +#if IS_ENABLED(CONFIG_MPLS)
> > + ipproto == IPPROTO_MPLS ||
> > +#endif
> > + ipproto == 0;
> > +}
>
> This returns true any time ipproto is not equal to IPPROTO_IPIP,
> which is probably not what you intended here.
Thanks, I will fix that.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP
2016-07-07 4:44 ` [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Tom Herbert
@ 2016-07-07 5:38 ` Simon Horman
0 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2016-07-07 5:38 UTC (permalink / raw)
To: Tom Herbert; +Cc: Linux Kernel Network Developers
On Wed, Jul 06, 2016 at 09:44:13PM -0700, Tom Herbert wrote:
> On Wed, Jul 6, 2016 at 11:22 AM, Simon Horman
> <simon.horman@netronome.com> wrote:
> > This short series provides support for MPLS in IPv4 (RFC4023), and by
> > virtue of FOU, MPLS in UDP (RFC7510).
> >
> > The changes are as follows:
> > 1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
> > AF_INET6
> > 2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
> > SIT also already handles IPv6.
> > 3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
> >
>
> HI Siomon,
>
> Thanks for these patches! Can provide the commands for testing this?
Sure, will do.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-07-07 5:38 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-06 18:22 [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 2/4] sit: support MPLS over IPv4 Simon Horman
2016-07-07 5:10 ` David Miller
2016-07-07 5:37 ` Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 3/4] ipip: " Simon Horman
2016-07-06 18:22 ` [PATCH/RFC net-next 4/4] mpls: allow routes on ipip and sit devices Simon Horman
2016-07-07 4:44 ` [PATCH/RFC net-next 0/4] net: support MPLS in IPv4 and UDP Tom Herbert
2016-07-07 5:38 ` Simon Horman
2016-07-07 5:12 ` David Miller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.