On Wed, Nov 27, 2019 at 02:55:14PM +0200, Roi Dayan wrote:
> From: Paul Blakey <[email protected]>
>
> Changelog:
> V1->V2:
> Missing ntohs/htons on nat port range.
>
> Signed-off-by: Paul Blakey <[email protected]>
> ---
> 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
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev