route: Per route IP tunnel metadata via lightweight tunnel
authorThomas Graf <tgraf@suug.ch>
Tue, 21 Jul 2015 08:44:00 +0000 (10:44 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2015 17:39:06 +0000 (10:39 -0700)
This introduces a new IP tunnel lightweight tunnel type which allows
to specify IP tunnel instructions per route. Only IPv4 is supported
at this point.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan.c
include/net/dst_metadata.h
include/net/ip_tunnels.h
include/uapi/linux/lwtunnel.h
include/uapi/linux/rtnetlink.h
net/ipv4/ip_tunnel_core.c
net/ipv4/route.c
net/openvswitch/vport.h

index 06c092b..9486d7e 100644 (file)
@@ -1935,7 +1935,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                           struct vxlan_rdst *rdst, bool did_rsc)
 {
-       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct ip_tunnel_info *info;
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct sock *sk = vxlan->vn_sock->sock->sk;
        struct rtable *rt = NULL;
@@ -1952,6 +1952,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
        int err;
        u32 flags = vxlan->flags;
 
+       /* FIXME: Support IPv6 */
+       info = skb_tunnel_info(skb, AF_INET);
+
        if (rdst) {
                dst_port = rdst->remote_port ? rdst->remote_port : vxlan->dst_port;
                vni = rdst->remote_vni;
@@ -2141,12 +2144,15 @@ tx_free:
 static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
-       const struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       const struct ip_tunnel_info *info;
        struct ethhdr *eth;
        bool did_rsc = false;
        struct vxlan_rdst *rdst, *fdst = NULL;
        struct vxlan_fdb *f;
 
+       /* FIXME: Support IPv6 */
+       info = skb_tunnel_info(skb, AF_INET);
+
        skb_reset_mac_header(skb);
        eth = eth_hdr(skb);
 
index e843937..7b03068 100644 (file)
@@ -23,13 +23,23 @@ static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb)
        return NULL;
 }
 
-static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb)
+static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb,
+                                                    int family)
 {
        struct metadata_dst *md_dst = skb_metadata_dst(skb);
+       struct rtable *rt;
 
        if (md_dst)
                return &md_dst->u.tun_info;
 
+       switch (family) {
+       case AF_INET:
+               rt = (struct rtable *)skb_dst(skb);
+               if (rt && rt->rt_lwtstate)
+                       return lwt_tun_info(rt->rt_lwtstate);
+               break;
+       }
+
        return NULL;
 }
 
index d11530f..0b7e18c 100644 (file)
@@ -9,9 +9,9 @@
 #include <net/dsfield.h>
 #include <net/gro_cells.h>
 #include <net/inet_ecn.h>
-#include <net/ip.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
+#include <net/lwtunnel.h>
 
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6.h>
@@ -298,6 +298,11 @@ static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info, size_t n)
        return info + 1;
 }
 
+static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate)
+{
+       return (struct ip_tunnel_info *)lwtstate->data;
+}
+
 #endif /* CONFIG_INET */
 
 #endif /* __NET_IP_TUNNELS_H */
index aa611d9..31377bb 100644 (file)
@@ -6,6 +6,7 @@
 enum lwtunnel_encap_types {
        LWTUNNEL_ENCAP_NONE,
        LWTUNNEL_ENCAP_MPLS,
+       LWTUNNEL_ENCAP_IP,
        __LWTUNNEL_ENCAP_MAX,
 };
 
Simple merge
Simple merge
Simple merge
Simple merge