On Wed, Nov 27, 2019 at 02:55:14PM +0200, Roi Dayan wrote: > From: Paul Blakey <pa...@mellanox.com> > > Changelog: > V1->V2: > Missing ntohs/htons on nat port range. > > Signed-off-by: Paul Blakey <pa...@mellanox.com> > --- > lib/netdev-offload-tc.c | 104 > ++++++++++++++++++++++++++++++++++++++++++++++++ > lib/tc.c | 91 ++++++++++++++++++++++++++++++++++++++++++ > lib/tc.h | 24 +++++++++++ > 3 files changed, 219 insertions(+) > > diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c > index 2b4ecfb9ca48..3a9b9e144311 100644 > --- a/lib/netdev-offload-tc.c > +++ b/lib/netdev-offload-tc.c > @@ -814,6 +814,40 @@ parse_tc_flower_to_match(struct tc_flower *flower, > ct_label->mask = action->ct.label_mask; > } > > + if (action->ct.nat_type) { > + size_t nat_offset = nl_msg_start_nested(buf, > + OVS_CT_ATTR_NAT); > + > + if (action->ct.nat_type == TC_NAT_SRC) { > + nl_msg_put_flag(buf, OVS_NAT_ATTR_SRC); > + } else if (action->ct.nat_type == TC_NAT_DST) { > + nl_msg_put_flag(buf, OVS_NAT_ATTR_DST); > + } > + > + if (action->ct.range.ip_family == AF_INET) { > + nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MIN, ^^^^^^^^^^^ > + action->ct.range.min_addr.ipv4); ^^^^^^^^
Sorry, more bikeshedding here. OVS seems to use _MIN and _MAX as suffix, and tc act ct also uses it that way: TCA_CT_NAT_IPV4_MIN, etc. I'm wondering, should we do the same for tc_action members here? > + nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MAX, > + action->ct.range.max_addr.ipv4); > + } else if (action->ct.range.ip_family == AF_INET6) { > + nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MIN, > + &action->ct.range.min_addr.ipv6); > + nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MAX, > + &action->ct.range.max_addr.ipv6); > + } > + > + if (action->ct.range.min_port) { > + nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MIN, > + ntohs(action->ct.range.min_port)); > + if (action->ct.range.max_port) { > + nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MAX, > + ntohs(action->ct.range.max_port)); > + } > + } > + > + nl_msg_end_nested(buf, nat_offset); > + } > + > nl_msg_end_nested(buf, ct_offset); > } > break; > @@ -906,6 +940,66 @@ parse_mpls_set_action(struct tc_flower *flower, struct > tc_action *action, > } > > static int > +parse_put_flow_nat_action(struct tc_action *action, > + const struct nlattr *nat, > + size_t nat_len) > +{ > + const struct nlattr *nat_attr; > + size_t nat_left; > + > + action->ct.nat_type = TC_NAT_RESTORE; > + NL_ATTR_FOR_EACH_UNSAFE (nat_attr, nat_left, nat, nat_len) { > + switch (nl_attr_type(nat_attr)) { > + case OVS_NAT_ATTR_SRC: { > + action->ct.nat_type = TC_NAT_SRC; > + }; > + break; > + case OVS_NAT_ATTR_DST: { > + action->ct.nat_type = TC_NAT_DST; > + }; > + break; > + case OVS_NAT_ATTR_IP_MIN: { > + if (nl_attr_get_size(nat_attr) == sizeof(ovs_be32)) { > + ovs_be32 addr = nl_attr_get_be32(nat_attr); > + > + action->ct.range.min_addr.ipv4 = addr; > + action->ct.range.ip_family = AF_INET; > + } else { > + struct in6_addr addr = nl_attr_get_in6_addr(nat_attr); > + > + action->ct.range.min_addr.ipv6 = addr; > + action->ct.range.ip_family = AF_INET6; > + } > + }; > + break; > + case OVS_NAT_ATTR_IP_MAX: { > + if (nl_attr_get_size(nat_attr) == sizeof(ovs_be32)) { > + ovs_be32 addr = nl_attr_get_be32(nat_attr); > + > + action->ct.range.max_addr.ipv4 = addr; > + action->ct.range.ip_family = AF_INET; > + } else { > + struct in6_addr addr = nl_attr_get_in6_addr(nat_attr); > + > + action->ct.range.max_addr.ipv6 = addr; > + action->ct.range.ip_family = AF_INET6; > + } > + }; > + break; > + case OVS_NAT_ATTR_PROTO_MIN: { > + action->ct.range.min_port = htons(nl_attr_get_u16(nat_attr)); > + }; > + break; > + case OVS_NAT_ATTR_PROTO_MAX: { > + action->ct.range.max_port = htons(nl_attr_get_u16(nat_attr)); > + }; > + break; > + } > + } > + return 0; > +} > + > +static int > parse_put_flow_ct_action(struct tc_flower *flower, > struct tc_action *action, > const struct nlattr *ct, > @@ -925,6 +1019,16 @@ parse_put_flow_ct_action(struct tc_flower *flower, > action->ct.zone = nl_attr_get_u16(ct_attr); > } > break; > + case OVS_CT_ATTR_NAT: { > + const struct nlattr *nat = nl_attr_get(ct_attr); > + const size_t nat_len = nl_attr_get_size(ct_attr); > + > + err = parse_put_flow_nat_action(action, nat, nat_len); > + if (err) { > + return err; > + } > + } > + break; > case OVS_CT_ATTR_MARK: { > const struct { > uint32_t key; > diff --git a/lib/tc.c b/lib/tc.c > index 1062326d4b86..83ee0f6473aa 100644 > --- a/lib/tc.c > +++ b/lib/tc.c > @@ -1282,6 +1282,18 @@ static const struct nl_policy ct_policy[] = { > .optional = true, }, > [TCA_CT_LABELS_MASK] = { .type = NL_A_UNSPEC, > .optional = true, }, > + [TCA_CT_NAT_IPV4_MIN] = { .type = NL_A_U32, > + .optional = true, }, > + [TCA_CT_NAT_IPV4_MAX] = { .type = NL_A_U32, > + .optional = true, }, > + [TCA_CT_NAT_IPV6_MIN] = { .min_len = sizeof(struct in6_addr), > + .optional = true, }, > + [TCA_CT_NAT_IPV6_MAX] = { .min_len = sizeof(struct in6_addr), > + .optional = true, }, > + [TCA_CT_NAT_PORT_MIN] = { .type = NL_A_U16, > + .optional = true, }, > + [TCA_CT_NAT_PORT_MAX] = { .type = NL_A_U16, > + .optional = true, }, > }; > > static int > @@ -1325,6 +1337,47 @@ nl_parse_act_ct(struct nlattr *options, struct > tc_flower *flower) > action->ct.label_mask = label_mask ? > nl_attr_get_u128(label_mask) : OVS_U128_ZERO; > > + if (ct_action & TCA_CT_ACT_NAT) { > + struct nlattr *ipv4_min = ct_attrs[TCA_CT_NAT_IPV4_MIN]; > + struct nlattr *ipv4_max = ct_attrs[TCA_CT_NAT_IPV4_MAX]; > + struct nlattr *ipv6_min = ct_attrs[TCA_CT_NAT_IPV6_MIN]; > + struct nlattr *ipv6_max = ct_attrs[TCA_CT_NAT_IPV6_MAX]; > + struct nlattr *min_port = ct_attrs[TCA_CT_NAT_PORT_MIN]; > + struct nlattr *max_port = ct_attrs[TCA_CT_NAT_PORT_MAX]; Ditto here. > + > + action->ct.nat_type = TC_NAT_RESTORE; > + if (ct_action & TCA_CT_ACT_NAT_SRC) { > + action->ct.nat_type = TC_NAT_SRC; > + } else if (ct_action & TCA_CT_ACT_NAT_DST) { > + action->ct.nat_type = TC_NAT_DST; > + } > + > + if (ipv4_min) { > + action->ct.range.ip_family = AF_INET; > + action->ct.range.min_addr.ipv4 = nl_attr_get_be32(ipv4_min); > + if (ipv4_max) { > + ovs_be32 port = nl_attr_get_be32(ipv4_max); > + > + action->ct.range.max_addr.ipv4 = port; > + } > + } else if (ipv6_min) { > + action->ct.range.ip_family = AF_INET6; > + action->ct.range.min_addr.ipv6 > + = nl_attr_get_in6_addr(ipv6_min); > + if (ipv6_max) { > + struct in6_addr addr = nl_attr_get_in6_addr(ipv6_max); > + > + action->ct.range.max_addr.ipv6 = addr; > + } > + } > + > + if (min_port) { > + action->ct.range.min_port = nl_attr_get_be16(min_port); > + if (max_port) { > + action->ct.range.max_port = nl_attr_get_be16(max_port); > + } > + } > + } > } > action->type = TC_ACT_CT; > > @@ -2056,6 +2109,44 @@ nl_msg_put_act_ct(struct ofpbuf *request, struct > tc_action *action) > ct_action |= TCA_CT_ACT_FORCE; > } > } > + > + if (action->ct.nat_type) { > + ct_action |= TCA_CT_ACT_NAT; > + > + if (action->ct.nat_type == TC_NAT_SRC) { > + ct_action |= TCA_CT_ACT_NAT_SRC; > + } else if (action->ct.nat_type == TC_NAT_DST) { > + ct_action |= TCA_CT_ACT_NAT_DST; > + } > + > + if (action->ct.range.ip_family == AF_INET) { > + nl_msg_put_be32(request, TCA_CT_NAT_IPV4_MIN, > + action->ct.range.min_addr.ipv4); > + if (action->ct.range.max_addr.ipv4) { > + nl_msg_put_be32(request, TCA_CT_NAT_IPV4_MAX, > + action->ct.range.max_addr.ipv4); > + } > + } else if (action->ct.range.ip_family == AF_INET6) { > + size_t ipv6_sz = sizeof(action->ct.range.max_addr.ipv6); > + > + nl_msg_put_in6_addr(request, TCA_CT_NAT_IPV6_MIN, > + &action->ct.range.min_addr.ipv6); > + if (!is_all_zeros(&action->ct.range.max_addr.ipv6, > + ipv6_sz)) { > + nl_msg_put_in6_addr(request, TCA_CT_NAT_IPV6_MAX, > + &action->ct.range.max_addr.ipv6); > + } > + } > + > + if (action->ct.range.min_port) { > + nl_msg_put_be16(request, TCA_CT_NAT_PORT_MIN, > + action->ct.range.min_port); > + if (action->ct.range.max_port) { > + nl_msg_put_be16(request, TCA_CT_NAT_PORT_MAX, > + action->ct.range.max_port); > + } > + } > + } > } else { > ct_action = TCA_CT_ACT_CLEAR; > } > diff --git a/lib/tc.h b/lib/tc.h > index e853aeb77468..15e58f88acb9 100644 > --- a/lib/tc.h > +++ b/lib/tc.h > @@ -165,6 +165,13 @@ enum tc_action_type { > TC_ACT_CT, > }; > > +enum nat_type { > + TC_NO_NAT = 0, > + TC_NAT_SRC, > + TC_NAT_DST, > + TC_NAT_RESTORE, > +}; > + > struct tc_action { > union { > int chain; > @@ -213,6 +220,23 @@ struct tc_action { > uint32_t mark_mask; > ovs_u128 label; > ovs_u128 label_mask; > + uint8_t nat_type; > + struct { > + uint8_t ip_family; > + > + union { > + struct in6_addr ipv6; > + ovs_be32 ipv4; > + } min_addr; > + > + union { > + struct in6_addr ipv6; > + ovs_be32 ipv4; > + } max_addr; > + > + ovs_be16 min_port; > + ovs_be16 max_port; > + } range; > bool clear; > bool force; > bool commit; > -- > 2.8.4 > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev