Extend ovs-tc translation by allowing non-byte-aligned fields for set actions. Use new boundary shifts and add set ipv6 traffic class action offload via pedit.
Signed-off-by: Pieter Jansen van Vuuren <[email protected]> Signed-off-by: Louis Peens <[email protected]> Reviewed-by: Simon Horman <[email protected]> --- lib/netdev-tc-offloads.c | 4 ++ lib/tc.c | 79 +++++++++++++++++++++++++++++++--------- lib/tc.h | 1 + 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c index 90bd3c585..1c5bd22e4 100644 --- a/lib/netdev-tc-offloads.c +++ b/lib/netdev-tc-offloads.c @@ -84,6 +84,10 @@ static struct netlink_field set_flower_map[][4] = { offsetof(struct tc_flower_key, ipv6.rewrite_hlimit), MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_hlimit) }, + { offsetof(struct ovs_key_ipv6, ipv6_tclass), + offsetof(struct tc_flower_key, ipv6.rewrite_tclass), + MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_tclass) + }, }, [OVS_KEY_ATTR_ETHERNET] = { { offsetof(struct ovs_key_ethernet, eth_src), diff --git a/lib/tc.c b/lib/tc.c index 1696c9836..c77d73b41 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -73,6 +73,7 @@ struct flower_key_to_pedit { int offset; int flower_offset; int size; + int boundary_shift; }; static struct flower_key_to_pedit flower_pedit_map[] = { @@ -80,72 +81,92 @@ static struct flower_key_to_pedit flower_pedit_map[] = { TCA_PEDIT_KEY_EX_HDR_TYPE_IP4, 12, offsetof(struct tc_flower_key, ipv4.ipv4_src), - MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_src) + MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_src), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP4, 16, offsetof(struct tc_flower_key, ipv4.ipv4_dst), - MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_dst) + MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_dst), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP4, 8, offsetof(struct tc_flower_key, ipv4.rewrite_ttl), - MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_ttl) + MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_ttl), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP4, 1, offsetof(struct tc_flower_key, ipv4.rewrite_tos), - MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_tos) + MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_tos), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP6, 7, offsetof(struct tc_flower_key, ipv6.rewrite_hlimit), - MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_hlimit) + MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_hlimit), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP6, 8, offsetof(struct tc_flower_key, ipv6.ipv6_src), - MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_src) + MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_src), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_IP6, 24, offsetof(struct tc_flower_key, ipv6.ipv6_dst), - MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_dst) + MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_dst), + 0 + }, { + TCA_PEDIT_KEY_EX_HDR_TYPE_IP6, + 0, + offsetof(struct tc_flower_key, ipv6.rewrite_tclass), + MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_tclass), + 4 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_ETH, 6, offsetof(struct tc_flower_key, src_mac), - MEMBER_SIZEOF(struct tc_flower_key, src_mac) + MEMBER_SIZEOF(struct tc_flower_key, src_mac), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_ETH, 0, offsetof(struct tc_flower_key, dst_mac), - MEMBER_SIZEOF(struct tc_flower_key, dst_mac) + MEMBER_SIZEOF(struct tc_flower_key, dst_mac), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_ETH, 12, offsetof(struct tc_flower_key, eth_type), - MEMBER_SIZEOF(struct tc_flower_key, eth_type) + MEMBER_SIZEOF(struct tc_flower_key, eth_type), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_TCP, 0, offsetof(struct tc_flower_key, tcp_src), - MEMBER_SIZEOF(struct tc_flower_key, tcp_src) + MEMBER_SIZEOF(struct tc_flower_key, tcp_src), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_TCP, 2, offsetof(struct tc_flower_key, tcp_dst), - MEMBER_SIZEOF(struct tc_flower_key, tcp_dst) + MEMBER_SIZEOF(struct tc_flower_key, tcp_dst), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_UDP, 0, offsetof(struct tc_flower_key, udp_src), - MEMBER_SIZEOF(struct tc_flower_key, udp_src) + MEMBER_SIZEOF(struct tc_flower_key, udp_src), + 0 }, { TCA_PEDIT_KEY_EX_HDR_TYPE_UDP, 2, offsetof(struct tc_flower_key, udp_dst), - MEMBER_SIZEOF(struct tc_flower_key, udp_dst) + MEMBER_SIZEOF(struct tc_flower_key, udp_dst), + 0 }, }; @@ -769,6 +790,22 @@ static const struct nl_policy pedit_policy[] = { .optional = false, }, }; +/* These functions specifically help shifting values that are in + * network byte order but stored in uint32_t variables. */ +static uint32_t shift_ovs_be32_left(uint32_t word, int shift) +{ + uint32_t word_shifted = ntohl((OVS_FORCE ovs_be32)word) << shift; + + return (OVS_FORCE uint32_t)htonl(word_shifted); +} + +static uint32_t shift_ovs_be32_right(uint32_t word, int shift) +{ + uint32_t word_shifted = ntohl((OVS_FORCE ovs_be32)word) >> shift; + + return (OVS_FORCE uint32_t)htonl(word_shifted); +} + static int nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) { @@ -832,8 +869,11 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) int diff = flower_off + (keys->off - mf); uint32_t *dst = (void *) (rewrite_key + diff); uint32_t *dst_m = (void *) (rewrite_mask + diff); - uint32_t mask = ~(keys->mask); - uint32_t zero_bits; + uint32_t mask_word, data_word, mask, zero_bits; + + mask_word = shift_ovs_be32_left(keys->mask, m->boundary_shift); + data_word = shift_ovs_be32_left(keys->val, m->boundary_shift); + mask = ~(mask_word); if (keys->off < mf) { zero_bits = 8 * (mf - keys->off); @@ -844,7 +884,7 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) } *dst_m |= mask; - *dst |= keys->val & mask; + *dst |= data_word & mask; } } @@ -1832,6 +1872,7 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, for (j = 0; j < cnt; j++, mask++, data++, cur_offset += 4) { uint32_t mask_word = *mask; + uint32_t data_word = *data; if (j == 0) { mask_word &= first_word_mask; @@ -1853,8 +1894,10 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, pedit_key_ex->cmd = TCA_PEDIT_KEY_EX_CMD_SET; pedit_key_ex->htype = m->htype; pedit_key->off = cur_offset; + mask_word = shift_ovs_be32_right(mask_word, m->boundary_shift); + data_word = shift_ovs_be32_right(data_word, m->boundary_shift); pedit_key->mask = ~mask_word; - pedit_key->val = *data & mask_word; + pedit_key->val = data_word & mask_word; sel.sel.nkeys++; err = csum_update_flag(flower, m->htype); diff --git a/lib/tc.h b/lib/tc.h index 04b08e298..6c909df21 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -109,6 +109,7 @@ struct tc_flower_key { struct in6_addr ipv6_src; struct in6_addr ipv6_dst; uint8_t rewrite_hlimit; + uint8_t rewrite_tclass; } ipv6; struct { -- 2.17.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
