5858#include <net/netevent.h>
5959#include <net/netlink.h>
6060#include <net/nexthop.h>
61+ #include <net/lwtunnel.h>
6162
6263#include <asm/uaccess.h>
6364
@@ -1770,6 +1771,17 @@ int ip6_route_add(struct fib6_config *cfg)
17701771
17711772 rt -> dst .output = ip6_output ;
17721773
1774+ if (cfg -> fc_encap ) {
1775+ struct lwtunnel_state * lwtstate ;
1776+
1777+ err = lwtunnel_build_state (dev , cfg -> fc_encap_type ,
1778+ cfg -> fc_encap , & lwtstate );
1779+ if (err )
1780+ goto out ;
1781+ lwtunnel_state_get (lwtstate );
1782+ rt -> rt6i_lwtstate = lwtstate ;
1783+ }
1784+
17731785 ipv6_addr_prefix (& rt -> rt6i_dst .addr , & cfg -> fc_dst , cfg -> fc_dst_len );
17741786 rt -> rt6i_dst .plen = cfg -> fc_dst_len ;
17751787 if (rt -> rt6i_dst .plen == 128 )
@@ -2595,6 +2607,8 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
25952607 [RTA_METRICS ] = { .type = NLA_NESTED },
25962608 [RTA_MULTIPATH ] = { .len = sizeof (struct rtnexthop ) },
25972609 [RTA_PREF ] = { .type = NLA_U8 },
2610+ [RTA_ENCAP_TYPE ] = { .type = NLA_U16 },
2611+ [RTA_ENCAP ] = { .type = NLA_NESTED },
25982612};
25992613
26002614static int rtm_to_fib6_config (struct sk_buff * skb , struct nlmsghdr * nlh ,
@@ -2689,6 +2703,12 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
26892703 cfg -> fc_flags |= RTF_PREF (pref );
26902704 }
26912705
2706+ if (tb [RTA_ENCAP ])
2707+ cfg -> fc_encap = tb [RTA_ENCAP ];
2708+
2709+ if (tb [RTA_ENCAP_TYPE ])
2710+ cfg -> fc_encap_type = nla_get_u16 (tb [RTA_ENCAP_TYPE ]);
2711+
26922712 err = 0 ;
26932713errout :
26942714 return err ;
@@ -2721,6 +2741,10 @@ static int ip6_route_multipath(struct fib6_config *cfg, int add)
27212741 r_cfg .fc_gateway = nla_get_in6_addr (nla );
27222742 r_cfg .fc_flags |= RTF_GATEWAY ;
27232743 }
2744+ r_cfg .fc_encap = nla_find (attrs , attrlen , RTA_ENCAP );
2745+ nla = nla_find (attrs , attrlen , RTA_ENCAP_TYPE );
2746+ if (nla )
2747+ r_cfg .fc_encap_type = nla_get_u16 (nla );
27242748 }
27252749 err = add ? ip6_route_add (& r_cfg ) : ip6_route_del (& r_cfg );
27262750 if (err ) {
@@ -2783,7 +2807,7 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
27832807 return ip6_route_add (& cfg );
27842808}
27852809
2786- static inline size_t rt6_nlmsg_size (void )
2810+ static inline size_t rt6_nlmsg_size (struct rt6_info * rt )
27872811{
27882812 return NLMSG_ALIGN (sizeof (struct rtmsg ))
27892813 + nla_total_size (16 ) /* RTA_SRC */
@@ -2797,7 +2821,8 @@ static inline size_t rt6_nlmsg_size(void)
27972821 + RTAX_MAX * nla_total_size (4 ) /* RTA_METRICS */
27982822 + nla_total_size (sizeof (struct rta_cacheinfo ))
27992823 + nla_total_size (TCP_CA_NAME_MAX ) /* RTAX_CC_ALGO */
2800- + nla_total_size (1 ); /* RTA_PREF */
2824+ + nla_total_size (1 ) /* RTA_PREF */
2825+ + lwtunnel_get_encap_size (rt -> rt6i_lwtstate );
28012826}
28022827
28032828static int rt6_fill_node (struct net * net ,
@@ -2945,6 +2970,8 @@ static int rt6_fill_node(struct net *net,
29452970 if (nla_put_u8 (skb , RTA_PREF , IPV6_EXTRACT_PREF (rt -> rt6i_flags )))
29462971 goto nla_put_failure ;
29472972
2973+ lwtunnel_fill_encap (skb , rt -> rt6i_lwtstate );
2974+
29482975 nlmsg_end (skb , nlh );
29492976 return 0 ;
29502977
@@ -3071,7 +3098,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
30713098 err = - ENOBUFS ;
30723099 seq = info -> nlh ? info -> nlh -> nlmsg_seq : 0 ;
30733100
3074- skb = nlmsg_new (rt6_nlmsg_size (), gfp_any ());
3101+ skb = nlmsg_new (rt6_nlmsg_size (rt ), gfp_any ());
30753102 if (!skb )
30763103 goto errout ;
30773104
0 commit comments