nexthop: Add support for lwt encaps
authorDavid Ahern <dsahern@gmail.com>
Fri, 24 May 2019 21:43:07 +0000 (14:43 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 29 May 2019 04:37:30 +0000 (21:37 -0700)
Add support for NHA_ENCAP and NHA_ENCAP_TYPE. Leverages the existing code
for lwtunnel within fib_nh_common, so the only change needed is handling
the attributes in the nexthop code.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/nexthop.h
net/ipv4/nexthop.c

index d188f16c0c4f646dfdc04e7e1cffd46d2032905c..7cde03337e14305fc5bc5817a7443db51a1a1797 100644 (file)
@@ -35,6 +35,9 @@ struct nh_config {
                struct in6_addr ipv6;
        } gw;
 
+       struct nlattr   *nh_encap;
+       u16             nh_encap_type;
+
        u32             nlflags;
        struct nl_info  nlinfo;
 };
index f2b237a6735cef0fc5beabfe720e86cc9ed5b230..3a1cbcb96baa51973969b9b9541f57cec577412f 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
 #include <net/ipv6_stubs.h>
+#include <net/lwtunnel.h>
 #include <net/nexthop.h>
 #include <net/route.h>
 #include <net/sock.h>
@@ -182,6 +183,11 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
                break;
        }
 
+       if (nhi->fib_nhc.nhc_lwtstate &&
+           lwtunnel_fill_encap(skb, nhi->fib_nhc.nhc_lwtstate,
+                               NHA_ENCAP, NHA_ENCAP_TYPE) < 0)
+               goto nla_put_failure;
+
 out:
        nlmsg_end(skb, nlh);
        return 0;
@@ -213,6 +219,11 @@ static size_t nh_nlmsg_size(struct nexthop *nh)
                break;
        }
 
+       if (nhi->fib_nhc.nhc_lwtstate) {
+               sz += lwtunnel_get_encap_size(nhi->fib_nhc.nhc_lwtstate);
+               sz += nla_total_size(2);  /* NHA_ENCAP_TYPE */
+       }
+
        return sz;
 }
 
@@ -370,6 +381,8 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh,
                .fc_gw4   = cfg->gw.ipv4,
                .fc_gw_family = cfg->gw.ipv4 ? AF_INET : 0,
                .fc_flags = cfg->nh_flags,
+               .fc_encap = cfg->nh_encap,
+               .fc_encap_type = cfg->nh_encap_type,
        };
        u32 tb_id = l3mdev_fib_table(cfg->dev);
        int err = -EINVAL;
@@ -402,6 +415,8 @@ static int nh_create_ipv6(struct net *net,  struct nexthop *nh,
                .fc_ifindex = cfg->nh_ifindex,
                .fc_gateway = cfg->gw.ipv6,
                .fc_flags = cfg->nh_flags,
+               .fc_encap = cfg->nh_encap,
+               .fc_encap_type = cfg->nh_encap_type,
        };
        int err = -EINVAL;
 
@@ -561,7 +576,8 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,
                cfg->nh_id = nla_get_u32(tb[NHA_ID]);
 
        if (tb[NHA_BLACKHOLE]) {
-               if (tb[NHA_GATEWAY] || tb[NHA_OIF]) {
+               if (tb[NHA_GATEWAY] || tb[NHA_OIF] ||
+                   tb[NHA_ENCAP]   || tb[NHA_ENCAP_TYPE]) {
                        NL_SET_ERR_MSG(extack, "Blackhole attribute can not be used with gateway or oif");
                        goto out;
                }
@@ -626,6 +642,25 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,
                }
        }
 
+       if (tb[NHA_ENCAP]) {
+               cfg->nh_encap = tb[NHA_ENCAP];
+
+               if (!tb[NHA_ENCAP_TYPE]) {
+                       NL_SET_ERR_MSG(extack, "LWT encapsulation type is missing");
+                       goto out;
+               }
+
+               cfg->nh_encap_type = nla_get_u16(tb[NHA_ENCAP_TYPE]);
+               err = lwtunnel_valid_encap_type(cfg->nh_encap_type, extack);
+               if (err < 0)
+                       goto out;
+
+       } else if (tb[NHA_ENCAP_TYPE]) {
+               NL_SET_ERR_MSG(extack, "LWT encapsulation attribute is missing");
+               goto out;
+       }
+
+
        err = 0;
 out:
        return err;