@@ -257,18 +257,36 @@ static int nla_put_port_range(struct sk_buff *skb, int attrtype,
257257 return nla_put (skb , attrtype , sizeof (* range ), range );
258258}
259259
260+ static bool fib_rule_iif_match (const struct fib_rule * rule , int iifindex ,
261+ const struct flowi * fl )
262+ {
263+ u8 iif_is_l3_master = READ_ONCE (rule -> iif_is_l3_master );
264+
265+ return iif_is_l3_master ? l3mdev_fib_rule_iif_match (fl , iifindex ) :
266+ fl -> flowi_iif == iifindex ;
267+ }
268+
269+ static bool fib_rule_oif_match (const struct fib_rule * rule , int oifindex ,
270+ const struct flowi * fl )
271+ {
272+ u8 oif_is_l3_master = READ_ONCE (rule -> oif_is_l3_master );
273+
274+ return oif_is_l3_master ? l3mdev_fib_rule_oif_match (fl , oifindex ) :
275+ fl -> flowi_oif == oifindex ;
276+ }
277+
260278static int fib_rule_match (struct fib_rule * rule , struct fib_rules_ops * ops ,
261279 struct flowi * fl , int flags ,
262280 struct fib_lookup_arg * arg )
263281{
264282 int iifindex , oifindex , ret = 0 ;
265283
266284 iifindex = READ_ONCE (rule -> iifindex );
267- if (iifindex && ( iifindex != fl -> flowi_iif ))
285+ if (iifindex && ! fib_rule_iif_match ( rule , iifindex , fl ))
268286 goto out ;
269287
270288 oifindex = READ_ONCE (rule -> oifindex );
271- if (oifindex && ( oifindex != fl -> flowi_oif ))
289+ if (oifindex && ! fib_rule_oif_match ( rule , oifindex , fl ))
272290 goto out ;
273291
274292 if ((rule -> mark ^ fl -> flowi_mark ) & rule -> mark_mask )
@@ -736,16 +754,20 @@ static int fib_nl2rule_rtnl(struct fib_rule *nlrule,
736754 struct net_device * dev ;
737755
738756 dev = __dev_get_by_name (nlrule -> fr_net , nlrule -> iifname );
739- if (dev )
757+ if (dev ) {
740758 nlrule -> iifindex = dev -> ifindex ;
759+ nlrule -> iif_is_l3_master = netif_is_l3_master (dev );
760+ }
741761 }
742762
743763 if (tb [FRA_OIFNAME ]) {
744764 struct net_device * dev ;
745765
746766 dev = __dev_get_by_name (nlrule -> fr_net , nlrule -> oifname );
747- if (dev )
767+ if (dev ) {
748768 nlrule -> oifindex = dev -> ifindex ;
769+ nlrule -> oif_is_l3_master = netif_is_l3_master (dev );
770+ }
749771 }
750772
751773 return 0 ;
@@ -1336,11 +1358,17 @@ static void attach_rules(struct list_head *rules, struct net_device *dev)
13361358
13371359 list_for_each_entry (rule , rules , list ) {
13381360 if (rule -> iifindex == -1 &&
1339- strcmp (dev -> name , rule -> iifname ) == 0 )
1361+ strcmp (dev -> name , rule -> iifname ) == 0 ) {
13401362 WRITE_ONCE (rule -> iifindex , dev -> ifindex );
1363+ WRITE_ONCE (rule -> iif_is_l3_master ,
1364+ netif_is_l3_master (dev ));
1365+ }
13411366 if (rule -> oifindex == -1 &&
1342- strcmp (dev -> name , rule -> oifname ) == 0 )
1367+ strcmp (dev -> name , rule -> oifname ) == 0 ) {
13431368 WRITE_ONCE (rule -> oifindex , dev -> ifindex );
1369+ WRITE_ONCE (rule -> oif_is_l3_master ,
1370+ netif_is_l3_master (dev ));
1371+ }
13441372 }
13451373}
13461374
@@ -1349,10 +1377,14 @@ static void detach_rules(struct list_head *rules, struct net_device *dev)
13491377 struct fib_rule * rule ;
13501378
13511379 list_for_each_entry (rule , rules , list ) {
1352- if (rule -> iifindex == dev -> ifindex )
1380+ if (rule -> iifindex == dev -> ifindex ) {
13531381 WRITE_ONCE (rule -> iifindex , -1 );
1354- if (rule -> oifindex == dev -> ifindex )
1382+ WRITE_ONCE (rule -> iif_is_l3_master , false);
1383+ }
1384+ if (rule -> oifindex == dev -> ifindex ) {
13551385 WRITE_ONCE (rule -> oifindex , -1 );
1386+ WRITE_ONCE (rule -> oif_is_l3_master , false);
1387+ }
13561388 }
13571389}
13581390
0 commit comments