From: Roopa Prabhu <ro...@cumulusnetworks.com> - parse RTA_ENCAP - store lwtstate in every nexthop - set dst->output to point to lwtunnel output
Signed-off-by: Roopa Prabhu <ro...@cumulusnetworks.com> --- include/net/dst.h | 2 ++ include/net/ip_fib.h | 5 ++++- net/ipv4/fib_frontend.c | 6 ++++++ net/ipv4/fib_semantics.c | 34 +++++++++++++++++++++++++++++++++- net/ipv4/route.c | 5 +++++ 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 2bc73f8a..111d128 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -103,6 +103,8 @@ struct dst_entry { struct rt6_info *rt6_next; struct dn_route __rcu *dn_next; }; + + struct lwtunnel_state __rcu *lwtstate; }; u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 54271ed..506a87e 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -44,7 +44,9 @@ struct fib_config { u32 fc_flow; u32 fc_nlflags; struct nl_info fc_nlinfo; - }; + struct rtencap *fc_encap; + int fc_encap_len; +}; struct fib_info; struct rtable; @@ -89,6 +91,7 @@ struct fib_nh { struct rtable __rcu * __percpu *nh_pcpu_rth_output; struct rtable __rcu *nh_rth_input; struct fnhe_hash_bucket __rcu *nh_exceptions; + struct lw_tunnel_state __rcu *lwtstate; }; /* diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 872494e..3f0a70e 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -656,6 +656,12 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, case RTA_TABLE: cfg->fc_table = nla_get_u32(attr); break; + case RTA_ENCAP: + { + cfg->fc_encap = nla_data(attr); + cfg->fc_encap_len = nla_len(attr); + break; + } } } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 28ec3c1..b69312f 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -42,6 +42,7 @@ #include <net/ip_fib.h> #include <net/netlink.h> #include <net/nexthop.h> +#include <net/lwtunnel.h> #include "fib_lookup.h" @@ -208,6 +209,8 @@ static void free_fib_info_rcu(struct rcu_head *head) change_nexthops(fi) { if (nexthop_nh->nh_dev) dev_put(nexthop_nh->nh_dev); + if (nexthop_nh->lwtstate) + lwtunnel_state_free(nexthop_nh->lwtstate); free_nh_exceptions(nexthop_nh); rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output); rt_fibinfo_free(&nexthop_nh->nh_rth_input); @@ -366,6 +369,7 @@ static inline size_t fib_nlmsg_size(struct fib_info *fi) payload += nla_total_size((RTAX_MAX * nla_total_size(4))); if (fi->fib_nhs) { + size_t nh_encapsize = 0; /* Also handles the special case fib_nhs == 1 */ /* each nexthop is packed in an attribute */ @@ -374,8 +378,19 @@ static inline size_t fib_nlmsg_size(struct fib_info *fi) /* may contain flow and gateway attribute */ nhsize += 2 * nla_total_size(4); + /* grab encap info */ + for_nexthops(fi) { + if (fi->fib_nh[0].lwtstate) + nh_encapsize += nla_total_size( + lw_tunnel_encap_size( + fi->fib_nh[0].lwtstate) + 2); + + } endfor_nexthops(fi); + /* all nexthops are packed in a nested attribute */ - payload += nla_total_size(fi->fib_nhs * nhsize); + payload += nla_total_size((fi->fib_nhs * nhsize) + + nh_encapsize); + } return payload; @@ -875,6 +890,19 @@ struct fib_info *fib_create_info(struct fib_config *cfg) } else { struct fib_nh *nh = fi->fib_nh; + if (cfg->fc_encap) { + struct lw_tunnel_state *lwtstate; + struct rtencap *encap = cfg->fc_encap; + int ret; + + ret = lw_tunnel_build_state(encap, cfg->fc_encap_len, + &lwtstate); + if (ret) + goto err_inval; + + nh->lwtstate = lwtstate; + } + nh->nh_oif = cfg->fc_oif; nh->nh_gw = cfg->fc_gw; nh->nh_flags = cfg->fc_flags; @@ -1034,6 +1062,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid)) goto nla_put_failure; #endif + if (fi->fib_nh->lwtstate) + lw_tunnel_dump_encap(skb, fi->fib_nh->lwtstate); } #ifdef CONFIG_IP_ROUTE_MULTIPATH if (fi->fib_nhs > 1) { @@ -1061,6 +1091,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid)) goto nla_put_failure; #endif + if (nh->lwtstate) + lw_tunnel_dump_encap(skb, nh->lwtstate); /* length of rtnetlink header + attributes */ rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh; } endfor_nexthops(fi); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f605598..0ed7da0 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -102,6 +102,7 @@ #include <net/tcp.h> #include <net/icmp.h> #include <net/xfrm.h> +#include <net/lwtunnel.h> #include <net/netevent.h> #include <net/rtnetlink.h> #ifdef CONFIG_SYSCTL @@ -1403,6 +1404,8 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid; #endif + if (nh->lwtstate) + rt->dst.lwtstate = nh->lwtstate; if (unlikely(fnhe)) cached = rt_bind_exception(rt, fnhe, daddr); else if (!(rt->dst.flags & DST_NOCACHE)) @@ -1624,6 +1627,8 @@ static int __mkroute_input(struct sk_buff *skb, rth->dst.output = ip_output; rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag); + if (rth->dst.lwtstate) + lwtunnel_dst_set_output(rth->dst.lwtstate, &rth->dst); skb_dst_set(skb, &rth->dst); out: err = 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html