Skip to content

Commit

Permalink
ipv6: support for fib route lwtunnel encap attributes
Browse files Browse the repository at this point in the history
This patch adds support in ipv6 fib functions to parse Netlink
RTA encap attributes and attach encap state data to rt6_info.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Roopa Prabhu authored and David S. Miller committed Jul 21, 2015
1 parent 571e722 commit 19e42e4
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/net/ip6_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct fib6_config {
struct nlattr *fc_mp;

struct nl_info fc_nlinfo;
struct nlattr *fc_encap;
u16 fc_encap_type;
};

struct fib6_node {
Expand Down Expand Up @@ -131,6 +133,7 @@ struct rt6_info {
/* more non-fragment space at head required */
unsigned short rt6i_nfheader_len;
u8 rt6i_protocol;
struct lwtunnel_state *rt6i_lwtstate;
};

static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
Expand Down
2 changes: 2 additions & 0 deletions net/ipv6/ip6_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <net/ipv6.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/lwtunnel.h>

#include <net/ip6_fib.h>
#include <net/ip6_route.h>
Expand Down Expand Up @@ -177,6 +178,7 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
static void rt6_release(struct rt6_info *rt)
{
if (atomic_dec_and_test(&rt->rt6i_ref)) {
lwtunnel_state_put(rt->rt6i_lwtstate);
rt6_free_pcpu(rt);
dst_free(&rt->dst);
}
Expand Down
33 changes: 30 additions & 3 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include <net/netevent.h>
#include <net/netlink.h>
#include <net/nexthop.h>
#include <net/lwtunnel.h>

#include <asm/uaccess.h>

Expand Down Expand Up @@ -1770,6 +1771,17 @@ int ip6_route_add(struct fib6_config *cfg)

rt->dst.output = ip6_output;

if (cfg->fc_encap) {
struct lwtunnel_state *lwtstate;

err = lwtunnel_build_state(dev, cfg->fc_encap_type,
cfg->fc_encap, &lwtstate);
if (err)
goto out;
lwtunnel_state_get(lwtstate);
rt->rt6i_lwtstate = lwtstate;
}

ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
rt->rt6i_dst.plen = cfg->fc_dst_len;
if (rt->rt6i_dst.plen == 128)
Expand Down Expand Up @@ -2595,6 +2607,8 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_METRICS] = { .type = NLA_NESTED },
[RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
[RTA_PREF] = { .type = NLA_U8 },
[RTA_ENCAP_TYPE] = { .type = NLA_U16 },
[RTA_ENCAP] = { .type = NLA_NESTED },
};

static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
Expand Down Expand Up @@ -2689,6 +2703,12 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
cfg->fc_flags |= RTF_PREF(pref);
}

if (tb[RTA_ENCAP])
cfg->fc_encap = tb[RTA_ENCAP];

if (tb[RTA_ENCAP_TYPE])
cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);

err = 0;
errout:
return err;
Expand Down Expand Up @@ -2721,6 +2741,10 @@ static int ip6_route_multipath(struct fib6_config *cfg, int add)
r_cfg.fc_gateway = nla_get_in6_addr(nla);
r_cfg.fc_flags |= RTF_GATEWAY;
}
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
if (nla)
r_cfg.fc_encap_type = nla_get_u16(nla);
}
err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
if (err) {
Expand Down Expand Up @@ -2783,7 +2807,7 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
return ip6_route_add(&cfg);
}

static inline size_t rt6_nlmsg_size(void)
static inline size_t rt6_nlmsg_size(struct rt6_info *rt)
{
return NLMSG_ALIGN(sizeof(struct rtmsg))
+ nla_total_size(16) /* RTA_SRC */
Expand All @@ -2797,7 +2821,8 @@ static inline size_t rt6_nlmsg_size(void)
+ RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
+ nla_total_size(sizeof(struct rta_cacheinfo))
+ nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
+ nla_total_size(1); /* RTA_PREF */
+ nla_total_size(1) /* RTA_PREF */
+ lwtunnel_get_encap_size(rt->rt6i_lwtstate);
}

static int rt6_fill_node(struct net *net,
Expand Down Expand Up @@ -2945,6 +2970,8 @@ static int rt6_fill_node(struct net *net,
if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
goto nla_put_failure;

lwtunnel_fill_encap(skb, rt->rt6i_lwtstate);

nlmsg_end(skb, nlh);
return 0;

Expand Down Expand Up @@ -3071,7 +3098,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
err = -ENOBUFS;
seq = info->nlh ? info->nlh->nlmsg_seq : 0;

skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
if (!skb)
goto errout;

Expand Down

0 comments on commit 19e42e4

Please sign in to comment.