Add UAPI to provide set of flags for matching, where the flags provided from user-space are mapped to flow-dissector flags. The 1st flag allows to match on whether the packet is an IP fragment and corresponds to the FLOW_DIS_IS_FRAGMENT flag.
Unified · Split
| @@ -458,11 +458,18 @@ enum { · 457 unmodified lines | ||
| 458 | 458 | TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */ |
| 459 | 459 | TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */ |
| 460 | 460 | TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */ |
| 461 | + | |
| 462 | + TCA_FLOWER_KEY_FLAGS, /* be32 */ | |
| 463 | + TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */ | |
| 461 | 464 | __TCA_FLOWER_MAX, |
| 462 | 465 | }; |
| 463 | 466 | |
| 464 | 467 | #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) |
| 465 | 468 | |
| 469 | +enum { | |
| 470 | + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0), | |
| 471 | +}; | |
| 472 | + | |
| 466 | 473 | /* Match-all classifier */ |
| 467 | 474 | |
| 468 | 475 | enum { |
| @@ -386,6 +386,8 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { · 385 unmodified lines | ||
| 386 | 386 | [TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK] = { .type = NLA_U16 }, |
| 387 | 387 | [TCA_FLOWER_KEY_ENC_UDP_DST_PORT] = { .type = NLA_U16 }, |
| 388 | 388 | [TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK] = { .type = NLA_U16 }, |
| 389 | + [TCA_FLOWER_KEY_FLAGS] = { .type = NLA_U32 }, | |
| 390 | + [TCA_FLOWER_KEY_FLAGS_MASK] = { .type = NLA_U32 }, | |
| 389 | 391 | }; |
| 390 | 392 | |
| 391 | 393 | static void fl_set_key_val(struct nlattr **tb, |
| @@ -420,6 +422,39 @@ static void fl_set_key_vlan(struct nlattr **tb, · 28 unmodified lines | ||
| 420 | 422 | } |
| 421 | 423 | } |
| 422 | 424 | |
| 425 | +static void fl_set_key_flag(u32 flower_key, u32 flower_mask, | |
| 426 | + u32 *dissector_key, u32 *dissector_mask, | |
| 427 | + u32 flower_flag_bit, u32 dissector_flag_bit) | |
| 428 | +{ | |
| 429 | + if (flower_mask & flower_flag_bit) { | |
| 430 | + *dissector_mask |= dissector_flag_bit; | |
| 431 | + if (flower_key & flower_flag_bit) | |
| 432 | + *dissector_key |= dissector_flag_bit; | |
| 433 | + } | |
| 434 | +} | |
| 435 | + | |
| 436 | +static void fl_set_key_flags(struct nlattr **tb, | |
| 437 | + u32 *flags_key, u32 *flags_mask) | |
| 438 | +{ | |
| 439 | + u32 key, mask; | |
| 440 | + | |
| 441 | + if (!tb[TCA_FLOWER_KEY_FLAGS]) | |
| 442 | + return; | |
| 443 | + | |
| 444 | + key = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS])); | |
| 445 | + | |
| 446 | + if (!tb[TCA_FLOWER_KEY_FLAGS_MASK]) | |
| 447 | + mask = ~0; | |
| 448 | + else | |
| 449 | + mask = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS_MASK])); | |
| 450 | + | |
| 451 | + *flags_key = 0; | |
| 452 | + *flags_mask = 0; | |
| 453 | + | |
| 454 | + fl_set_key_flag(key, mask, flags_key, flags_mask, | |
| 455 | + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT); | |
| 456 | +} | |
| 457 | + | |
| 423 | 458 | static int fl_set_key(struct net *net, struct nlattr **tb, |
| 424 | 459 | struct fl_flow_key *key, struct fl_flow_key *mask) |
| 425 | 460 | { |
| @@ -546,6 +581,8 @@ static int fl_set_key(struct net *net, struct nlattr **tb, · 120 unmodified lines | ||
| 546 | 581 | &mask->enc_tp.dst, TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, |
| 547 | 582 | sizeof(key->enc_tp.dst)); |
| 548 | 583 | |
| 584 | + fl_set_key_flags(tb, &key->control.flags, &mask->control.flags); | |
| 585 | + | |
| 549 | 586 | return 0; |
| 550 | 587 | } |
| 551 | 588 | |
| @@ -880,6 +917,42 @@ static int fl_dump_key_vlan(struct sk_buff *skb, · 328 unmodified lines | ||
| 880 | 917 | return 0; |
| 881 | 918 | } |
| 882 | 919 | |
| 920 | +static void fl_get_key_flag(u32 dissector_key, u32 dissector_mask, | |
| 921 | + u32 *flower_key, u32 *flower_mask, | |
| 922 | + u32 flower_flag_bit, u32 dissector_flag_bit) | |
| 923 | +{ | |
| 924 | + if (dissector_mask & dissector_flag_bit) { | |
| 925 | + *flower_mask |= flower_flag_bit; | |
| 926 | + if (dissector_key & dissector_flag_bit) | |
| 927 | + *flower_key |= flower_flag_bit; | |
| 928 | + } | |
| 929 | +} | |
| 930 | + | |
| 931 | +static int fl_dump_key_flags(struct sk_buff *skb, u32 flags_key, u32 flags_mask) | |
| 932 | +{ | |
| 933 | + u32 key, mask; | |
| 934 | + __be32 _key, _mask; | |
| 935 | + int err; | |
| 936 | + | |
| 937 | + if (!memchr_inv(&flags_mask, 0, sizeof(flags_mask))) | |
| 938 | + return 0; | |
| 939 | + | |
| 940 | + key = 0; | |
| 941 | + mask = 0; | |
| 942 | + | |
| 943 | + fl_get_key_flag(flags_key, flags_mask, &key, &mask, | |
| 944 | + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT); | |
| 945 | + | |
| 946 | + _key = cpu_to_be32(key); | |
| 947 | + _mask = cpu_to_be32(mask); | |
| 948 | + | |
| 949 | + err = nla_put(skb, TCA_FLOWER_KEY_FLAGS, 4, &_key); | |
| 950 | + if (err) | |
| 951 | + return err; | |
| 952 | + | |
| 953 | + return nla_put(skb, TCA_FLOWER_KEY_FLAGS_MASK, 4, &_mask); | |
| 954 | +} | |
| 955 | + | |
| 883 | 956 | static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, |
| 884 | 957 | struct sk_buff *skb, struct tcmsg *t) |
| 885 | 958 | { |
| @@ -1015,6 +1088,9 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, · 129 unmodified lines | ||
| 1015 | 1088 | sizeof(key->enc_tp.dst))) |
| 1016 | 1089 | goto nla_put_failure; |
| 1017 | 1090 | |
| 1091 | + if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags)) | |
| 1092 | + goto nla_put_failure; | |
| 1093 | + | |
| 1018 | 1094 | nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags); |
| 1019 | 1095 | |
| 1020 | 1096 | if (tcf_exts_dump(skb, &f->exts)) |