New matches for conntrack mark, label, zone, and state.
Unified · Split
| @@ -537,11 +537,27 @@ enum { · 536 unmodified lines | |||
| 537 | TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */ | 537 | TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */ |
| 538 | TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */ | 538 | TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */ |
| 539 | 539 | ||
| 540 | TCA_FLOWER_KEY_CT_STATE, /* u16 */ | ||
| 541 | TCA_FLOWER_KEY_CT_STATE_MASK, /* u16 */ | ||
| 542 | TCA_FLOWER_KEY_CT_ZONE, /* u16 */ | ||
| 543 | TCA_FLOWER_KEY_CT_ZONE_MASK, /* u16 */ | ||
| 544 | TCA_FLOWER_KEY_CT_MARK, /* u32 */ | ||
| 545 | TCA_FLOWER_KEY_CT_MARK_MASK, /* u32 */ | ||
| 546 | TCA_FLOWER_KEY_CT_LABELS, /* u128 */ | ||
| 547 | TCA_FLOWER_KEY_CT_LABELS_MASK, /* u128 */ | ||
| 548 | |||
| 540 | __TCA_FLOWER_MAX, | 549 | __TCA_FLOWER_MAX, |
| 541 | }; | 550 | }; |
| 542 | 551 | ||
| 543 | #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) | 552 | #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) |
| 544 | 553 | ||
| 554 | enum { | ||
| 555 | TCA_FLOWER_KEY_CT_FLAGS_NEW = 1 << 0, /* Beginning of a new connection. */ | ||
| 556 | TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */ | ||
| 557 | TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */ | ||
| 558 | TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */ | ||
| 559 | }; | ||
| 560 | |||
| 545 | enum { | 561 | enum { |
| 546 | TCA_FLOWER_KEY_ENC_OPTS_UNSPEC, | 562 | TCA_FLOWER_KEY_ENC_OPTS_UNSPEC, |
| 547 | TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested | 563 | TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include <net/dst.h> | 26 | #include <net/dst.h> |
| 27 | #include <net/dst_metadata.h> | 27 | #include <net/dst_metadata.h> |
| 28 | 28 | ||
| 29 | #include <uapi/linux/netfilter/nf_conntrack_common.h> | ||
| 30 | |||
| 29 | struct fl_flow_key { | 31 | struct fl_flow_key { |
| 30 | struct flow_dissector_key_meta meta; | 32 | struct flow_dissector_key_meta meta; |
| 31 | struct flow_dissector_key_control control; | 33 | struct flow_dissector_key_control control; |
| @@ -54,6 +56,7 @@ struct fl_flow_key { · 22 unmodified lines | |||
| 54 | struct flow_dissector_key_enc_opts enc_opts; | 56 | struct flow_dissector_key_enc_opts enc_opts; |
| 55 | struct flow_dissector_key_ports tp_min; | 57 | struct flow_dissector_key_ports tp_min; |
| 56 | struct flow_dissector_key_ports tp_max; | 58 | struct flow_dissector_key_ports tp_max; |
| 59 | struct flow_dissector_key_ct ct; | ||
| 57 | } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ | 60 | } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ |
| 58 | 61 | ||
| 59 | struct fl_flow_mask_range { | 62 | struct fl_flow_mask_range { |
| @@ -272,14 +275,27 @@ static struct cls_fl_filter *fl_lookup(struct fl_flow_mask *mask, · 212 unmodified lines | |||
| 272 | return __fl_lookup(mask, mkey); | 275 | return __fl_lookup(mask, mkey); |
| 273 | } | 276 | } |
| 274 | 277 | ||
| 278 | static u16 fl_ct_info_to_flower_map[] = { | ||
| 279 | [IP_CT_ESTABLISHED] = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | | ||
| 280 | TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED, | ||
| 281 | [IP_CT_RELATED] = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | | ||
| 282 | TCA_FLOWER_KEY_CT_FLAGS_RELATED, | ||
| 283 | [IP_CT_ESTABLISHED_REPLY] = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | | ||
| 284 | TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED, | ||
| 285 | [IP_CT_RELATED_REPLY] = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | | ||
| 286 | TCA_FLOWER_KEY_CT_FLAGS_RELATED, | ||
| 287 | [IP_CT_NEW] = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | | ||
| 288 | TCA_FLOWER_KEY_CT_FLAGS_NEW, | ||
| 289 | }; | ||
| 290 | |||
| 275 | static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, | 291 | static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
| 276 | struct tcf_result *res) | 292 | struct tcf_result *res) |
| 277 | { | 293 | { |
| 278 | struct cls_fl_head *head = rcu_dereference_bh(tp->root); | 294 | struct cls_fl_head *head = rcu_dereference_bh(tp->root); |
| 279 | struct cls_fl_filter *f; | ||
| 280 | struct fl_flow_mask *mask; | ||
| 281 | struct fl_flow_key skb_key; | ||
| 282 | struct fl_flow_key skb_mkey; | 295 | struct fl_flow_key skb_mkey; |
| 296 | struct fl_flow_key skb_key; | ||
| 297 | struct fl_flow_mask *mask; | ||
| 298 | struct cls_fl_filter *f; | ||
| 283 | 299 | ||
| 284 | list_for_each_entry_rcu(mask, &head->masks, list) { | 300 | list_for_each_entry_rcu(mask, &head->masks, list) { |
| 285 | fl_clear_masked_range(&skb_key, mask); | 301 | fl_clear_masked_range(&skb_key, mask); |
| @@ -290,6 +306,9 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, · 4 unmodified lines | |||
| 290 | */ | 306 | */ |
| 291 | skb_key.basic.n_proto = skb->protocol; | 307 | skb_key.basic.n_proto = skb->protocol; |
| 292 | skb_flow_dissect_tunnel_info(skb, &mask->dissector, &skb_key); | 308 | skb_flow_dissect_tunnel_info(skb, &mask->dissector, &skb_key); |
| 309 | skb_flow_dissect_ct(skb, &mask->dissector, &skb_key, | ||
| 310 | fl_ct_info_to_flower_map, | ||
| 311 | ARRAY_SIZE(fl_ct_info_to_flower_map)); | ||
| 293 | skb_flow_dissect(skb, &mask->dissector, &skb_key, 0); | 312 | skb_flow_dissect(skb, &mask->dissector, &skb_key, 0); |
| 294 | 313 | ||
| 295 | fl_set_masked_key(&skb_mkey, &skb_key, mask); | 314 | fl_set_masked_key(&skb_mkey, &skb_key, mask); |
| @@ -686,6 +705,16 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { · 390 unmodified lines | |||
| 686 | [TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 }, | 705 | [TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 }, |
| 687 | [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED }, | 706 | [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED }, |
| 688 | [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED }, | 707 | [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED }, |
| 708 | [TCA_FLOWER_KEY_CT_STATE] = { .type = NLA_U16 }, | ||
| 709 | [TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NLA_U16 }, | ||
| 710 | [TCA_FLOWER_KEY_CT_ZONE] = { .type = NLA_U16 }, | ||
| 711 | [TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NLA_U16 }, | ||
| 712 | [TCA_FLOWER_KEY_CT_MARK] = { .type = NLA_U32 }, | ||
| 713 | [TCA_FLOWER_KEY_CT_MARK_MASK] = { .type = NLA_U32 }, | ||
| 714 | [TCA_FLOWER_KEY_CT_LABELS] = { .type = NLA_BINARY, | ||
| 715 | .len = 128 / BITS_PER_BYTE }, | ||
| 716 | [TCA_FLOWER_KEY_CT_LABELS_MASK] = { .type = NLA_BINARY, | ||
| 717 | .len = 128 / BITS_PER_BYTE }, | ||
| 689 | }; | 718 | }; |
| 690 | 719 | ||
| 691 | static const struct nla_policy | 720 | static const struct nla_policy |
| @@ -707,11 +736,11 @@ static void fl_set_key_val(struct nlattr **tb, · 15 unmodified lines | |||
| 707 | { | 736 | { |
| 708 | if (!tb[val_type]) | 737 | if (!tb[val_type]) |
| 709 | return; | 738 | return; |
| 710 | memcpy(val, nla_data(tb[val_type]), len); | 739 | nla_memcpy(val, tb[val_type], len); |
| 711 | if (mask_type == TCA_FLOWER_UNSPEC || !tb[mask_type]) | 740 | if (mask_type == TCA_FLOWER_UNSPEC || !tb[mask_type]) |
| 712 | memset(mask, 0xff, len); | 741 | memset(mask, 0xff, len); |
| 713 | else | 742 | else |
| 714 | memcpy(mask, nla_data(tb[mask_type]), len); | 743 | nla_memcpy(mask, tb[mask_type], len); |
| 715 | } | 744 | } |
| 716 | 745 | ||
| 717 | static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key, | 746 | static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key, |
| @@ -997,6 +1026,51 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key, · 279 unmodified lines | |||
| 997 | return 0; | 1026 | return 0; |
| 998 | } | 1027 | } |
| 999 | 1028 | ||
| 1029 | static int fl_set_key_ct(struct nlattr **tb, | ||
| 1030 | struct flow_dissector_key_ct *key, | ||
| 1031 | struct flow_dissector_key_ct *mask, | ||
| 1032 | struct netlink_ext_ack *extack) | ||
| 1033 | { | ||
| 1034 | if (tb[TCA_FLOWER_KEY_CT_STATE]) { | ||
| 1035 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK)) { | ||
| 1036 | NL_SET_ERR_MSG(extack, "Conntrack isn't enabled"); | ||
| 1037 | return -EOPNOTSUPP; | ||
| 1038 | } | ||
| 1039 | fl_set_key_val(tb, &key->ct_state, TCA_FLOWER_KEY_CT_STATE, | ||
| 1040 | &mask->ct_state, TCA_FLOWER_KEY_CT_STATE_MASK, | ||
| 1041 | sizeof(key->ct_state)); | ||
| 1042 | } | ||
| 1043 | if (tb[TCA_FLOWER_KEY_CT_ZONE]) { | ||
| 1044 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES)) { | ||
| 1045 | NL_SET_ERR_MSG(extack, "Conntrack zones isn't enabled"); | ||
| 1046 | return -EOPNOTSUPP; | ||
| 1047 | } | ||
| 1048 | fl_set_key_val(tb, &key->ct_zone, TCA_FLOWER_KEY_CT_ZONE, | ||
| 1049 | &mask->ct_zone, TCA_FLOWER_KEY_CT_ZONE_MASK, | ||
| 1050 | sizeof(key->ct_zone)); | ||
| 1051 | } | ||
| 1052 | if (tb[TCA_FLOWER_KEY_CT_MARK]) { | ||
| 1053 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)) { | ||
| 1054 | NL_SET_ERR_MSG(extack, "Conntrack mark isn't enabled"); | ||
| 1055 | return -EOPNOTSUPP; | ||
| 1056 | } | ||
| 1057 | fl_set_key_val(tb, &key->ct_mark, TCA_FLOWER_KEY_CT_MARK, | ||
| 1058 | &mask->ct_mark, TCA_FLOWER_KEY_CT_MARK_MASK, | ||
| 1059 | sizeof(key->ct_mark)); | ||
| 1060 | } | ||
| 1061 | if (tb[TCA_FLOWER_KEY_CT_LABELS]) { | ||
| 1062 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS)) { | ||
| 1063 | NL_SET_ERR_MSG(extack, "Conntrack labels aren't enabled"); | ||
| 1064 | return -EOPNOTSUPP; | ||
| 1065 | } | ||
| 1066 | fl_set_key_val(tb, key->ct_labels, TCA_FLOWER_KEY_CT_LABELS, | ||
| 1067 | mask->ct_labels, TCA_FLOWER_KEY_CT_LABELS_MASK, | ||
| 1068 | sizeof(key->ct_labels)); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | return 0; | ||
| 1072 | } | ||
| 1073 | |||
| 1000 | static int fl_set_key(struct net *net, struct nlattr **tb, | 1074 | static int fl_set_key(struct net *net, struct nlattr **tb, |
| 1001 | struct fl_flow_key *key, struct fl_flow_key *mask, | 1075 | struct fl_flow_key *key, struct fl_flow_key *mask, |
| 1002 | struct netlink_ext_ack *extack) | 1076 | struct netlink_ext_ack *extack) |
| @@ -1206,6 +1280,10 @@ static int fl_set_key(struct net *net, struct nlattr **tb, · 203 unmodified lines | |||
| 1206 | return ret; | 1280 | return ret; |
| 1207 | } | 1281 | } |
| 1208 | 1282 | ||
| 1283 | ret = fl_set_key_ct(tb, &key->ct, &mask->ct, extack); | ||
| 1284 | if (ret) | ||
| 1285 | return ret; | ||
| 1286 | |||
| 1209 | if (tb[TCA_FLOWER_KEY_FLAGS]) | 1287 | if (tb[TCA_FLOWER_KEY_FLAGS]) |
| 1210 | ret = fl_set_key_flags(tb, &key->control.flags, &mask->control.flags); | 1288 | ret = fl_set_key_flags(tb, &key->control.flags, &mask->control.flags); |
| 1211 | 1289 | ||
| @@ -1306,6 +1384,8 @@ static void fl_init_dissector(struct flow_dissector *dissector, · 94 unmodified lines | |||
| 1306 | FLOW_DISSECTOR_KEY_ENC_IP, enc_ip); | 1384 | FLOW_DISSECTOR_KEY_ENC_IP, enc_ip); |
| 1307 | FL_KEY_SET_IF_MASKED(mask, keys, cnt, | 1385 | FL_KEY_SET_IF_MASKED(mask, keys, cnt, |
| 1308 | FLOW_DISSECTOR_KEY_ENC_OPTS, enc_opts); | 1386 | FLOW_DISSECTOR_KEY_ENC_OPTS, enc_opts); |
| 1387 | FL_KEY_SET_IF_MASKED(mask, keys, cnt, | ||
| 1388 | FLOW_DISSECTOR_KEY_CT, ct); | ||
| 1309 | 1389 | ||
| 1310 | skb_flow_dissector_init(dissector, keys, cnt); | 1390 | skb_flow_dissector_init(dissector, keys, cnt); |
| 1311 | } | 1391 | } |
| @@ -2065,6 +2145,40 @@ nla_put_failure: · 753 unmodified lines | |||
| 2065 | return -EMSGSIZE; | 2145 | return -EMSGSIZE; |
| 2066 | } | 2146 | } |
| 2067 | 2147 | ||
| 2148 | static int fl_dump_key_ct(struct sk_buff *skb, | ||
| 2149 | struct flow_dissector_key_ct *key, | ||
| 2150 | struct flow_dissector_key_ct *mask) | ||
| 2151 | { | ||
| 2152 | if (IS_ENABLED(CONFIG_NF_CONNTRACK) && | ||
| 2153 | fl_dump_key_val(skb, &key->ct_state, TCA_FLOWER_KEY_CT_STATE, | ||
| 2154 | &mask->ct_state, TCA_FLOWER_KEY_CT_STATE_MASK, | ||
| 2155 | sizeof(key->ct_state))) | ||
| 2156 | goto nla_put_failure; | ||
| 2157 | |||
| 2158 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && | ||
| 2159 | fl_dump_key_val(skb, &key->ct_zone, TCA_FLOWER_KEY_CT_ZONE, | ||
| 2160 | &mask->ct_zone, TCA_FLOWER_KEY_CT_ZONE_MASK, | ||
| 2161 | sizeof(key->ct_zone))) | ||
| 2162 | goto nla_put_failure; | ||
| 2163 | |||
| 2164 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && | ||
| 2165 | fl_dump_key_val(skb, &key->ct_mark, TCA_FLOWER_KEY_CT_MARK, | ||
| 2166 | &mask->ct_mark, TCA_FLOWER_KEY_CT_MARK_MASK, | ||
| 2167 | sizeof(key->ct_mark))) | ||
| 2168 | goto nla_put_failure; | ||
| 2169 | |||
| 2170 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && | ||
| 2171 | fl_dump_key_val(skb, &key->ct_labels, TCA_FLOWER_KEY_CT_LABELS, | ||
| 2172 | &mask->ct_labels, TCA_FLOWER_KEY_CT_LABELS_MASK, | ||
| 2173 | sizeof(key->ct_labels))) | ||
| 2174 | goto nla_put_failure; | ||
| 2175 | |||
| 2176 | return 0; | ||
| 2177 | |||
| 2178 | nla_put_failure: | ||
| 2179 | return -EMSGSIZE; | ||
| 2180 | } | ||
| 2181 | |||
| 2068 | static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type, | 2182 | static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type, |
| 2069 | struct flow_dissector_key_enc_opts *enc_opts) | 2183 | struct flow_dissector_key_enc_opts *enc_opts) |
| 2070 | { | 2184 | { |
| @@ -2298,6 +2412,9 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net, · 227 unmodified lines | |||
| 2298 | fl_dump_key_enc_opt(skb, &key->enc_opts, &mask->enc_opts)) | 2412 | fl_dump_key_enc_opt(skb, &key->enc_opts, &mask->enc_opts)) |
| 2299 | goto nla_put_failure; | 2413 | goto nla_put_failure; |
| 2300 | 2414 | ||
| 2415 | if (fl_dump_key_ct(skb, &key->ct, &mask->ct)) | ||
| 2416 | goto nla_put_failure; | ||
| 2417 | |||
| 2301 | if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags)) | 2418 | if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags)) |
| 2302 | goto nla_put_failure; | 2419 | goto nla_put_failure; |
| 2303 | 2420 | ||