@@ -1601,6 +1601,8 @@ dpif_netlink_netdev_match_to_dpif_flow(struct match *match,
.recirc = true,
.ct_state = true,
.ct_zone = true,
+ .ct_mark = true,
+ .ct_label = true,
},
};
size_t offset;
@@ -626,6 +626,8 @@ parse_tc_flower_to_match(struct tc_flower *flower,
}
match_set_ct_zone_masked(match, key->ct_zone, mask->ct_zone);
+ match_set_ct_mark_masked(match, key->ct_mark, mask->ct_mark);
+ match_set_ct_label_masked(match, key->ct_label, mask->ct_label);
}
if (flower->tunnel) {
@@ -757,6 +759,23 @@ parse_tc_flower_to_match(struct tc_flower *flower,
nl_msg_put_u16(buf, OVS_CT_ATTR_ZONE, action->ct.zone);
}
+ if (action->ct.mark_mask) {
+ uint32_t mark_and_mask[2] = { action->ct.mark, action->ct.mark_mask };
+ nl_msg_put_unspec(buf, OVS_CT_ATTR_MARK, &mark_and_mask, sizeof mark_and_mask);
+ }
+
+ if (!ovs_u128_is_zero(action->ct.label_mask)) {
+ struct {
+ ovs_u128 key;
+ ovs_u128 mask;
+ } *ct_label;
+
+ ct_label = nl_msg_put_unspec_uninit(buf, OVS_CT_ATTR_LABELS,
+ sizeof *ct_label);
+ ct_label->key = action->ct.label;
+ ct_label->mask = action->ct.label_mask;
+ }
+
nl_msg_end_nested(buf, ct_offset);
}
break;
@@ -851,6 +870,28 @@ parse_put_flow_ct_action(struct tc_flower *flower,
action->ct.zone = nl_attr_get_u16(ct_attr);
}
break;
+ case OVS_CT_ATTR_MARK: {
+ const struct {
+ uint32_t key;
+ uint32_t mask;
+ } *ct_mark;
+
+ ct_mark = nl_attr_get_unspec(ct_attr, sizeof *ct_mark);
+ action->ct.mark = ct_mark->key;
+ action->ct.mark_mask = ct_mark->mask;
+ }
+ break;
+ case OVS_CT_ATTR_LABELS: {
+ const struct {
+ ovs_u128 key;
+ ovs_u128 mask;
+ } *ct_label;
+
+ ct_label = nl_attr_get_unspec(ct_attr, sizeof *ct_label);
+ action->ct.label = ct_label->key;
+ action->ct.label_mask = ct_label->mask;
+ }
+ break;
}
}
@@ -1037,22 +1078,12 @@ test_key_and_mask(struct match *match)
return EOPNOTSUPP;
}
- if (mask->ct_mark) {
- VLOG_DBG_RL(&rl, "offloading attribute ct_mark isn't supported");
- return EOPNOTSUPP;
- }
-
if (mask->packet_type && key->packet_type) {
VLOG_DBG_RL(&rl, "offloading attribute packet_type isn't supported");
return EOPNOTSUPP;
}
mask->packet_type = 0;
- if (!ovs_u128_is_zero(mask->ct_label)) {
- VLOG_DBG_RL(&rl, "offloading attribute ct_label isn't supported");
- return EOPNOTSUPP;
- }
-
for (int i = 0; i < FLOW_N_REGS; i++) {
if (mask->regs[i]) {
VLOG_DBG_RL(&rl,
@@ -1407,6 +1438,18 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
mask->ct_zone = 0;
}
+ if (mask->ct_mark) {
+ flower.key.ct_mark = key->ct_mark;
+ flower.mask.ct_mark = mask->ct_mark;
+ mask->ct_mark = 0;
+ }
+
+ if (!ovs_u128_is_zero(mask->ct_label)) {
+ flower.key.ct_label = key->ct_label;
+ flower.mask.ct_label = mask->ct_label;
+ mask->ct_label = OVS_U128_ZERO;
+ }
+
err = test_key_and_mask(match);
if (err) {
return err;
@@ -403,6 +403,11 @@ static const struct nl_policy tca_flower_policy[] = {
[TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NL_A_U16, .optional = true, },
[TCA_FLOWER_KEY_CT_ZONE] = { .type = NL_A_U16, .optional = true, },
[TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NL_A_U16, .optional = true, },
+ [TCA_FLOWER_KEY_CT_MARK] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_CT_MARK_MASK] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_CT_LABELS] = { .type = NL_A_U128, .optional = true, },
+ [TCA_FLOWER_KEY_CT_LABELS_MASK] = { .type = NL_A_U128,
+ .optional = true, },
};
static void
@@ -813,6 +818,16 @@ nl_parse_flower_ip(struct nlattr **attrs, struct tc_flower *flower) {
key->ct_zone = nl_attr_get_u16(attrs[TCA_FLOWER_KEY_CT_ZONE]);
mask->ct_zone = nl_attr_get_u16(attrs[TCA_FLOWER_KEY_CT_ZONE_MASK]);
}
+
+ if (attrs[TCA_FLOWER_KEY_CT_MARK_MASK]) {
+ key->ct_mark = nl_attr_get_u32(attrs[TCA_FLOWER_KEY_CT_MARK]);
+ mask->ct_mark = nl_attr_get_u32(attrs[TCA_FLOWER_KEY_CT_MARK_MASK]);
+ }
+
+ if (attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]) {
+ key->ct_label = nl_attr_get_u128(attrs[TCA_FLOWER_KEY_CT_LABELS]);
+ mask->ct_label = nl_attr_get_u128(attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]);
+ }
}
static enum tc_offloaded_state
@@ -1241,6 +1256,14 @@ static const struct nl_policy ct_policy[] = {
.optional = true, },
[TCA_CT_ZONE] = { .type = NL_A_U16,
.optional = true, },
+ [TCA_CT_MARK] = { .type = NL_A_U32,
+ .optional = true, },
+ [TCA_CT_MARK_MASK] = { .type = NL_A_U32,
+ .optional = true, },
+ [TCA_CT_LABELS] = { .type = NL_A_UNSPEC,
+ .optional = true, },
+ [TCA_CT_LABELS_MASK] = { .type = NL_A_UNSPEC,
+ .optional = true, },
};
static int
@@ -1268,11 +1291,20 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower)
action->ct.clear = ct_action & TCA_CT_ACT_CLEAR;
if (!action->ct.clear) {
struct nlattr *zone = ct_attrs[TCA_CT_ZONE];
+ struct nlattr *mark = ct_attrs[TCA_CT_MARK];
+ struct nlattr *mark_mask = ct_attrs[TCA_CT_MARK_MASK];
+ struct nlattr *label = ct_attrs[TCA_CT_LABELS];
+ struct nlattr *label_mask = ct_attrs[TCA_CT_LABELS_MASK];
action->ct.commit = ct_action & TCA_CT_ACT_COMMIT;
action->ct.force = ct_action & TCA_CT_ACT_FORCE;
action->ct.zone = zone ? nl_attr_get_u16(zone) : 0;
+ action->ct.mark = mark ? nl_attr_get_u32(mark) : 0;
+ action->ct.mark_mask = mark_mask ? nl_attr_get_u32(mark_mask) : 0;
+ action->ct.label = label? nl_attr_get_u128(label) : OVS_U128_ZERO;
+ action->ct.label_mask = label_mask ?
+ nl_attr_get_u128(label_mask) : OVS_U128_ZERO;
}
action->type = TC_ACT_CT;
@@ -1829,6 +1861,21 @@ nl_msg_put_act_ct(struct ofpbuf *request, struct tc_action *action)
nl_msg_put_u16(request, TCA_CT_ZONE, action->ct.zone);
}
+ if (!is_all_zeros(&action->ct.label_mask,
+ sizeof action->ct.label_mask)) {
+ nl_msg_put_u128(request, TCA_CT_LABELS,
+ action->ct.label);
+ nl_msg_put_u128(request, TCA_CT_LABELS_MASK,
+ action->ct.label_mask);
+ }
+
+ if (action->ct.mark_mask) {
+ nl_msg_put_u32(request, TCA_CT_MARK,
+ action->ct.mark);
+ nl_msg_put_u32(request, TCA_CT_MARK_MASK,
+ action->ct.mark_mask);
+ }
+
if (action->ct.commit) {
ct_action = TCA_CT_ACT_COMMIT;
if (action->ct.force) {
@@ -2332,6 +2379,7 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
FLOWER_PUT_MASKED_VALUE(ct_state, TCA_FLOWER_KEY_CT_STATE);
FLOWER_PUT_MASKED_VALUE(ct_zone, TCA_FLOWER_KEY_CT_ZONE);
+ FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS);
}
if (host_eth_type == ETH_P_IP) {
@@ -118,6 +118,8 @@ struct tc_flower_key {
uint16_t ct_state;
uint16_t ct_zone;
+ uint32_t ct_mark;
+ ovs_u128 ct_label;
struct {
ovs_be32 ipv4_src;
@@ -196,6 +198,10 @@ struct tc_action {
struct {
uint16_t zone;
+ uint32_t mark;
+ uint32_t mark_mask;
+ ovs_u128 label;
+ ovs_u128 label_mask;
bool clear;
bool force;
bool commit;
Signed-off-by: Paul Blakey <paulb@mellanox.com> --- lib/dpif-netlink.c | 2 ++ lib/netdev-offload-tc.c | 63 +++++++++++++++++++++++++++++++++++++++++-------- lib/tc.c | 48 +++++++++++++++++++++++++++++++++++++ lib/tc.h | 6 +++++ 4 files changed, 109 insertions(+), 10 deletions(-)