Message ID | 20191127125516.5135-8-roid@mellanox.com |
---|---|
State | Superseded |
Headers | show |
Series | Add support for offloading CT datapath rules to TC | expand |
On Wed, Nov 27, 2019 at 02:55:13PM +0200, Roi Dayan wrote: > From: Paul Blakey <paulb@mellanox.com> > > Signed-off-by: Paul Blakey <paulb@mellanox.com> > --- > lib/dpif-netlink.c | 2 ++ > lib/netdev-offload-tc.c | 66 +++++++++++++++++++++++++++++++++++++++++-------- > lib/tc.c | 52 ++++++++++++++++++++++++++++++++++++++ > lib/tc.h | 6 +++++ > 4 files changed, 116 insertions(+), 10 deletions(-) > > diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c > index 620e94ea4bfc..22ba7cb360fb 100644 > --- a/lib/dpif-netlink.c > +++ b/lib/dpif-netlink.c > @@ -1603,6 +1603,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; > diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c > index 8dd48ab7c421..2b4ecfb9ca48 100644 > --- a/lib/netdev-offload-tc.c > +++ b/lib/netdev-offload-tc.c > @@ -623,6 +623,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) { > @@ -792,6 +794,26 @@ 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; > @@ -903,6 +925,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; > } > } > > @@ -1093,22 +1137,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, > @@ -1467,6 +1501,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; > diff --git a/lib/tc.c b/lib/tc.c > index 841552e1e4a6..1062326d4b86 100644 > --- a/lib/tc.c > +++ b/lib/tc.c > @@ -404,6 +404,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 > @@ -726,6 +731,20 @@ nl_parse_flower_ct_match(struct nlattr **attrs, struct tc_flower *flower) { > key->ct_zone = nl_attr_get_u16(attr_key); > mask->ct_zone = nl_attr_get_u16(attr_mask); > } > + > + attr_key = attrs[TCA_FLOWER_KEY_CT_MARK]; > + attr_mask = attrs[TCA_FLOWER_KEY_CT_MARK_MASK]; > + if (attrs[TCA_FLOWER_KEY_CT_MARK_MASK]) { > + key->ct_mark = nl_attr_get_u32(attr_key); > + mask->ct_mark = nl_attr_get_u32(attr_mask); > + } > + > + attr_key = attrs[TCA_FLOWER_KEY_CT_LABELS]; > + attr_mask = attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]; > + if (attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]) { > + key->ct_label = nl_attr_get_u128(attr_key); > + mask->ct_label = nl_attr_get_u128(attr_mask); > + } > } > > static void > @@ -1255,6 +1274,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 > @@ -1283,11 +1310,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; > @@ -1999,6 +2035,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) { > @@ -2539,6 +2590,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); Why not also? + FLOWER_PUT_MASKED_VALUE(ct_mark, TCA_FLOWER_KEY_CT_MARK); > + FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS); > } > > if (host_eth_type == ETH_P_IP) { > diff --git a/lib/tc.h b/lib/tc.h > index b1e2174b7369..e853aeb77468 100644 > --- a/lib/tc.h > +++ b/lib/tc.h > @@ -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; > @@ -207,6 +209,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; > -- > 2.8.4 >
On 11/27/2019 5:06 PM, Marcelo Ricardo Leitner wrote: > On Wed, Nov 27, 2019 at 02:55:13PM +0200, Roi Dayan wrote: >> @@ -1999,6 +2035,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) { >> @@ -2539,6 +2590,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); > Why not also? > + FLOWER_PUT_MASKED_VALUE(ct_mark, TCA_FLOWER_KEY_CT_MARK); Forgotten :) thanks. > >> + FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS); >> } >> >> if (host_eth_type == ETH_P_IP) { >>
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 620e94ea4bfc..22ba7cb360fb 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -1603,6 +1603,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; diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 8dd48ab7c421..2b4ecfb9ca48 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -623,6 +623,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) { @@ -792,6 +794,26 @@ 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; @@ -903,6 +925,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; } } @@ -1093,22 +1137,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, @@ -1467,6 +1501,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; diff --git a/lib/tc.c b/lib/tc.c index 841552e1e4a6..1062326d4b86 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -404,6 +404,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 @@ -726,6 +731,20 @@ nl_parse_flower_ct_match(struct nlattr **attrs, struct tc_flower *flower) { key->ct_zone = nl_attr_get_u16(attr_key); mask->ct_zone = nl_attr_get_u16(attr_mask); } + + attr_key = attrs[TCA_FLOWER_KEY_CT_MARK]; + attr_mask = attrs[TCA_FLOWER_KEY_CT_MARK_MASK]; + if (attrs[TCA_FLOWER_KEY_CT_MARK_MASK]) { + key->ct_mark = nl_attr_get_u32(attr_key); + mask->ct_mark = nl_attr_get_u32(attr_mask); + } + + attr_key = attrs[TCA_FLOWER_KEY_CT_LABELS]; + attr_mask = attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]; + if (attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]) { + key->ct_label = nl_attr_get_u128(attr_key); + mask->ct_label = nl_attr_get_u128(attr_mask); + } } static void @@ -1255,6 +1274,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 @@ -1283,11 +1310,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; @@ -1999,6 +2035,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) { @@ -2539,6 +2590,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) { diff --git a/lib/tc.h b/lib/tc.h index b1e2174b7369..e853aeb77468 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -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; @@ -207,6 +209,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;