6161#include <net/nexthop.h>
6262#include <net/lwtunnel.h>
6363#include <net/ip_tunnels.h>
64+ #include <net/l3mdev.h>
6465
6566#include <asm/uaccess.h>
6667
@@ -1044,6 +1045,9 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
10441045 fn = fib6_lookup (& table -> tb6_root , & fl6 -> daddr , & fl6 -> saddr );
10451046 saved_fn = fn ;
10461047
1048+ if (fl6 -> flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF )
1049+ oif = 0 ;
1050+
10471051redo_rt6_select :
10481052 rt = rt6_select (fn , oif , strict );
10491053 if (rt -> rt6i_nsiblings )
@@ -1141,7 +1145,7 @@ void ip6_route_input(struct sk_buff *skb)
11411145 int flags = RT6_LOOKUP_F_HAS_SADDR ;
11421146 struct ip_tunnel_info * tun_info ;
11431147 struct flowi6 fl6 = {
1144- .flowi6_iif = skb -> dev -> ifindex ,
1148+ .flowi6_iif = l3mdev_fib_oif ( skb -> dev ) ,
11451149 .daddr = iph -> daddr ,
11461150 .saddr = iph -> saddr ,
11471151 .flowlabel = ip6_flowinfo (iph ),
@@ -1165,8 +1169,13 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table
11651169struct dst_entry * ip6_route_output (struct net * net , const struct sock * sk ,
11661170 struct flowi6 * fl6 )
11671171{
1172+ struct dst_entry * dst ;
11681173 int flags = 0 ;
11691174
1175+ dst = l3mdev_rt6_dst_by_oif (net , fl6 );
1176+ if (dst )
1177+ return dst ;
1178+
11701179 fl6 -> flowi6_iif = LOOPBACK_IFINDEX ;
11711180
11721181 if ((sk && sk -> sk_bound_dev_if ) || rt6_need_strict (& fl6 -> daddr ) ||
@@ -2263,7 +2272,6 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
22632272 unsigned int pref )
22642273{
22652274 struct fib6_config cfg = {
2266- .fc_table = RT6_TABLE_INFO ,
22672275 .fc_metric = IP6_RT_PRIO_USER ,
22682276 .fc_ifindex = ifindex ,
22692277 .fc_dst_len = prefixlen ,
@@ -2274,6 +2282,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
22742282 .fc_nlinfo .nl_net = net ,
22752283 };
22762284
2285+ cfg .fc_table = l3mdev_fib_table_by_index (net , ifindex ) ? : RT6_TABLE_INFO ;
22772286 cfg .fc_dst = * prefix ;
22782287 cfg .fc_gateway = * gwaddr ;
22792288
@@ -2314,7 +2323,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
23142323 unsigned int pref )
23152324{
23162325 struct fib6_config cfg = {
2317- .fc_table = RT6_TABLE_DFLT ,
2326+ .fc_table = l3mdev_fib_table ( dev ) ? : RT6_TABLE_DFLT ,
23182327 .fc_metric = IP6_RT_PRIO_USER ,
23192328 .fc_ifindex = dev -> ifindex ,
23202329 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
@@ -2361,7 +2370,8 @@ static void rtmsg_to_fib6_config(struct net *net,
23612370{
23622371 memset (cfg , 0 , sizeof (* cfg ));
23632372
2364- cfg -> fc_table = RT6_TABLE_MAIN ;
2373+ cfg -> fc_table = l3mdev_fib_table_by_index (net , rtmsg -> rtmsg_ifindex ) ?
2374+ : RT6_TABLE_MAIN ;
23652375 cfg -> fc_ifindex = rtmsg -> rtmsg_ifindex ;
23662376 cfg -> fc_metric = rtmsg -> rtmsg_metric ;
23672377 cfg -> fc_expires = rtmsg -> rtmsg_info ;
@@ -2470,6 +2480,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
24702480 const struct in6_addr * addr ,
24712481 bool anycast )
24722482{
2483+ u32 tb_id ;
24732484 struct net * net = dev_net (idev -> dev );
24742485 struct rt6_info * rt = ip6_dst_alloc (net , net -> loopback_dev ,
24752486 DST_NOCOUNT );
@@ -2492,7 +2503,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
24922503 rt -> rt6i_gateway = * addr ;
24932504 rt -> rt6i_dst .addr = * addr ;
24942505 rt -> rt6i_dst .plen = 128 ;
2495- rt -> rt6i_table = fib6_get_table (net , RT6_TABLE_LOCAL );
2506+ tb_id = l3mdev_fib_table (idev -> dev ) ? : RT6_TABLE_LOCAL ;
2507+ rt -> rt6i_table = fib6_get_table (net , tb_id );
24962508 rt -> dst .flags |= DST_NOCACHE ;
24972509
24982510 atomic_set (& rt -> dst .__refcnt , 1 );
@@ -3254,6 +3266,11 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
32543266 } else {
32553267 fl6 .flowi6_oif = oif ;
32563268
3269+ if (netif_index_is_l3_master (net , oif )) {
3270+ fl6 .flowi6_flags = FLOWI_FLAG_L3MDEV_SRC |
3271+ FLOWI_FLAG_SKIP_NH_OIF ;
3272+ }
3273+
32573274 rt = (struct rt6_info * )ip6_route_output (net , NULL , & fl6 );
32583275 }
32593276
0 commit comments