@@ -256,18 +256,36 @@ static int nla_put_port_range(struct sk_buff *skb, int attrtype,
256256 return nla_put (skb , attrtype , sizeof (* range ), range );
257257}
258258
259+ static bool fib_rule_iif_match (const struct fib_rule * rule , int iifindex ,
260+ const struct flowi * fl )
261+ {
262+ u8 iif_is_l3_master = READ_ONCE (rule -> iif_is_l3_master );
263+
264+ return iif_is_l3_master ? l3mdev_fib_rule_iif_match (fl , iifindex ) :
265+ fl -> flowi_iif == iifindex ;
266+ }
267+
268+ static bool fib_rule_oif_match (const struct fib_rule * rule , int oifindex ,
269+ const struct flowi * fl )
270+ {
271+ u8 oif_is_l3_master = READ_ONCE (rule -> oif_is_l3_master );
272+
273+ return oif_is_l3_master ? l3mdev_fib_rule_oif_match (fl , oifindex ) :
274+ fl -> flowi_oif == oifindex ;
275+ }
276+
259277static int fib_rule_match (struct fib_rule * rule , struct fib_rules_ops * ops ,
260278 struct flowi * fl , int flags ,
261279 struct fib_lookup_arg * arg )
262280{
263281 int iifindex , oifindex , ret = 0 ;
264282
265283 iifindex = READ_ONCE (rule -> iifindex );
266- if (iifindex && ( iifindex != fl -> flowi_iif ))
284+ if (iifindex && ! fib_rule_iif_match ( rule , iifindex , fl ))
267285 goto out ;
268286
269287 oifindex = READ_ONCE (rule -> oifindex );
270- if (oifindex && ( oifindex != fl -> flowi_oif ))
288+ if (oifindex && ! fib_rule_oif_match ( rule , oifindex , fl ))
271289 goto out ;
272290
273291 if ((rule -> mark ^ fl -> flowi_mark ) & rule -> mark_mask )
@@ -567,8 +585,10 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
567585 nlrule -> iifindex = -1 ;
568586 nla_strscpy (nlrule -> iifname , tb [FRA_IIFNAME ], IFNAMSIZ );
569587 dev = __dev_get_by_name (net , nlrule -> iifname );
570- if (dev )
588+ if (dev ) {
571589 nlrule -> iifindex = dev -> ifindex ;
590+ nlrule -> iif_is_l3_master = netif_is_l3_master (dev );
591+ }
572592 }
573593
574594 if (tb [FRA_OIFNAME ]) {
@@ -577,8 +597,10 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
577597 nlrule -> oifindex = -1 ;
578598 nla_strscpy (nlrule -> oifname , tb [FRA_OIFNAME ], IFNAMSIZ );
579599 dev = __dev_get_by_name (net , nlrule -> oifname );
580- if (dev )
600+ if (dev ) {
581601 nlrule -> oifindex = dev -> ifindex ;
602+ nlrule -> oif_is_l3_master = netif_is_l3_master (dev );
603+ }
582604 }
583605
584606 if (tb [FRA_FWMARK ]) {
@@ -1218,11 +1240,17 @@ static void attach_rules(struct list_head *rules, struct net_device *dev)
12181240
12191241 list_for_each_entry (rule , rules , list ) {
12201242 if (rule -> iifindex == -1 &&
1221- strcmp (dev -> name , rule -> iifname ) == 0 )
1243+ strcmp (dev -> name , rule -> iifname ) == 0 ) {
12221244 WRITE_ONCE (rule -> iifindex , dev -> ifindex );
1245+ WRITE_ONCE (rule -> iif_is_l3_master ,
1246+ netif_is_l3_master (dev ));
1247+ }
12231248 if (rule -> oifindex == -1 &&
1224- strcmp (dev -> name , rule -> oifname ) == 0 )
1249+ strcmp (dev -> name , rule -> oifname ) == 0 ) {
12251250 WRITE_ONCE (rule -> oifindex , dev -> ifindex );
1251+ WRITE_ONCE (rule -> oif_is_l3_master ,
1252+ netif_is_l3_master (dev ));
1253+ }
12261254 }
12271255}
12281256
@@ -1231,10 +1259,14 @@ static void detach_rules(struct list_head *rules, struct net_device *dev)
12311259 struct fib_rule * rule ;
12321260
12331261 list_for_each_entry (rule , rules , list ) {
1234- if (rule -> iifindex == dev -> ifindex )
1262+ if (rule -> iifindex == dev -> ifindex ) {
12351263 WRITE_ONCE (rule -> iifindex , -1 );
1236- if (rule -> oifindex == dev -> ifindex )
1264+ WRITE_ONCE (rule -> iif_is_l3_master , false);
1265+ }
1266+ if (rule -> oifindex == dev -> ifindex ) {
12371267 WRITE_ONCE (rule -> oifindex , -1 );
1268+ WRITE_ONCE (rule -> oif_is_l3_master , false);
1269+ }
12381270 }
12391271}
12401272
0 commit comments