diff --git a/SOURCES/openvswitch-2.15.0.patch b/SOURCES/openvswitch-2.15.0.patch index 8254bed..a9123ea 100644 --- a/SOURCES/openvswitch-2.15.0.patch +++ b/SOURCES/openvswitch-2.15.0.patch @@ -21034,7 +21034,7 @@ index f2413f5be6..0e4119c0a6 100644 } ds_put_cstr(s, "/ "); diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c -index 72b7915052..0dd29b66d7 100644 +index 72b7915052..50e13dc1da 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -48,6 +48,7 @@ static struct hmap ufid_to_tc = HMAP_INITIALIZER(&ufid_to_tc); @@ -21045,6 +21045,20 @@ index 72b7915052..0dd29b66d7 100644 struct netlink_field { int offset; +@@ -411,10 +412,10 @@ netdev_tc_flow_dump_destroy(struct netdev_flow_dump *dump) + + static void + parse_flower_rewrite_to_netlink_action(struct ofpbuf *buf, +- struct tc_flower *flower) ++ struct tc_action *action) + { +- char *mask = (char *) &flower->rewrite.mask; +- char *data = (char *) &flower->rewrite.key; ++ char *mask = (char *) &action->rewrite.mask; ++ char *data = (char *) &action->rewrite.key; + + for (int type = 0; type < ARRAY_SIZE(set_flower_map); type++) { + char *put = NULL; @@ -515,8 +516,10 @@ parse_tc_flower_to_stats(struct tc_flower *flower, } @@ -21086,6 +21100,15 @@ index 72b7915052..0dd29b66d7 100644 match_set_ct_state_masked(match, ct_statev, ct_statem); } +@@ -780,7 +804,7 @@ parse_tc_flower_to_match(struct tc_flower *flower, + } + break; + case TC_ACT_PEDIT: { +- parse_flower_rewrite_to_netlink_action(buf, flower); ++ parse_flower_rewrite_to_netlink_action(buf, action); + } + break; + case TC_ACT_ENCAP: { @@ -820,8 +844,7 @@ parse_tc_flower_to_match(struct tc_flower *flower, action->encap.tp_dst); } @@ -21096,7 +21119,42 @@ index 72b7915052..0dd29b66d7 100644 } parse_tc_flower_geneve_opts(action, buf); -@@ -1406,6 +1429,90 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, +@@ -1126,8 +1149,8 @@ parse_put_flow_set_masked_action(struct tc_flower *flower, + uint64_t set_stub[1024 / 8]; + struct ofpbuf set_buf = OFPBUF_STUB_INITIALIZER(set_stub); + char *set_data, *set_mask; +- char *key = (char *) &flower->rewrite.key; +- char *mask = (char *) &flower->rewrite.mask; ++ char *key = (char *) &action->rewrite.key; ++ char *mask = (char *) &action->rewrite.mask; + const struct nlattr *attr; + int i, j, type; + size_t size; +@@ -1169,14 +1192,6 @@ parse_put_flow_set_masked_action(struct tc_flower *flower, + } + } + +- if (!is_all_zeros(&flower->rewrite, sizeof flower->rewrite)) { +- if (flower->rewrite.rewrite == false) { +- flower->rewrite.rewrite = true; +- action->type = TC_ACT_PEDIT; +- flower->action_count++; +- } +- } +- + if (hasmask && !is_all_zeros(set_mask, size)) { + VLOG_DBG_RL(&rl, "unsupported sub attribute of set action type %d", + type); +@@ -1185,6 +1200,8 @@ parse_put_flow_set_masked_action(struct tc_flower *flower, + } + + ofpbuf_uninit(&set_buf); ++ action->type = TC_ACT_PEDIT; ++ flower->action_count++; + return 0; + } + +@@ -1406,6 +1423,90 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len; } @@ -21187,7 +21245,7 @@ index 72b7915052..0dd29b66d7 100644 static int netdev_tc_flow_put(struct netdev *netdev, struct match *match, struct nlattr *actions, size_t actions_len, -@@ -1650,54 +1757,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, +@@ -1650,54 +1751,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, } } @@ -21243,7 +21301,33 @@ index 72b7915052..0dd29b66d7 100644 /* ignore exact match on skb_mark of 0. */ if (mask->pkt_mark == UINT32_MAX && !key->pkt_mark) { -@@ -1779,6 +1839,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, +@@ -1724,7 +1778,25 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, + VLOG_DBG_RL(&rl, "Can't find netdev for output port %d", port); + return ENODEV; + } ++ ++ if (!netdev_flow_api_equals(netdev, outdev)) { ++ VLOG_DBG_RL(&rl, ++ "Flow API provider mismatch between ingress (%s) " ++ "and egress (%s) ports", ++ netdev_get_name(netdev), netdev_get_name(outdev)); ++ netdev_close(outdev); ++ return EOPNOTSUPP; ++ } ++ + action->out.ifindex_out = netdev_get_ifindex(outdev); ++ if (action->out.ifindex_out < 0) { ++ VLOG_DBG_RL(&rl, ++ "Can't find ifindex for output port %s, error %d", ++ netdev_get_name(outdev), action->out.ifindex_out); ++ netdev_close(outdev); ++ return -action->out.ifindex_out; ++ } ++ + action->out.ingress = is_internal_port(netdev_get_type(outdev)); + action->type = TC_ACT_OUTPUT; + flower.action_count++; +@@ -1779,6 +1851,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, const struct nlattr *ct = nl_attr_get(nla); const size_t ct_len = nl_attr_get_size(nla); @@ -21254,7 +21338,7 @@ index 72b7915052..0dd29b66d7 100644 err = parse_put_flow_ct_action(&flower, action, ct, ct_len); if (err) { return err; -@@ -1894,9 +1958,7 @@ netdev_tc_flow_del(struct netdev *netdev OVS_UNUSED, +@@ -1894,9 +1970,7 @@ netdev_tc_flow_del(struct netdev *netdev OVS_UNUSED, if (stats) { memset(stats, 0, sizeof *stats); if (!tc_get_flower(&id, &flower)) { @@ -21265,7 +21349,7 @@ index 72b7915052..0dd29b66d7 100644 } } -@@ -1971,6 +2033,96 @@ out: +@@ -1971,6 +2045,96 @@ out: tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS); } @@ -21362,7 +21446,7 @@ index 72b7915052..0dd29b66d7 100644 static void probe_tc_block_support(int ifindex) { -@@ -2038,6 +2190,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) +@@ -2038,6 +2202,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) block_id = get_block_id_from_netdev(netdev); probe_multi_mask_per_prio(ifindex); @@ -21384,7 +21468,7 @@ index 47077e9478..5cb96fa6ec 100644 } else { txn->error = 0; diff --git a/lib/odp-util.c b/lib/odp-util.c -index a8598d52af..6245e0c26b 100644 +index a8598d52af..102003fc80 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2937,7 +2937,7 @@ odp_nsh_key_from_attr__(const struct nlattr *attr, bool is_mask, @@ -21431,7 +21515,19 @@ index a8598d52af..6245e0c26b 100644 &opts, sizeof(opts)); } nl_msg_end_nested(a, tun_key_ofs); -@@ -4614,7 +4614,7 @@ odp_flow_format(const struct nlattr *key, size_t key_len, +@@ -4597,6 +4597,11 @@ odp_flow_format(const struct nlattr *key, size_t key_len, + ds_put_char(ds, ','); + } + ds_put_cstr(ds, "eth()"); ++ } else if (attr_type == OVS_KEY_ATTR_PACKET_TYPE && is_wildcard) { ++ /* See the above help text, however in the case where the ++ * packet type is not shown, we still need to display the ++ * eth() header if the packets type is wildcarded. */ ++ has_packet_type_key = false; + } + ofpbuf_clear(&ofp); + } +@@ -4614,7 +4619,7 @@ odp_flow_format(const struct nlattr *key, size_t key_len, } ds_put_char(ds, ')'); } @@ -22254,10 +22350,110 @@ index 809b405a52..a869b5f390 100644 goto out; } diff --git a/lib/tc.c b/lib/tc.c -index 3192207984..57c30ed290 100644 +index 3192207984..2113934310 100644 --- a/lib/tc.c +++ b/lib/tc.c -@@ -1652,6 +1652,9 @@ static const struct nl_policy stats_policy[] = { +@@ -544,16 +544,17 @@ nl_parse_flower_vlan(struct nlattr **attrs, struct tc_flower *flower) + + flower->key.encap_eth_type[0] = + nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ETH_TYPE]); ++ flower->mask.encap_eth_type[0] = CONSTANT_HTONS(0xffff); + + if (attrs[TCA_FLOWER_KEY_VLAN_ID]) { + flower->key.vlan_id[0] = + nl_attr_get_u16(attrs[TCA_FLOWER_KEY_VLAN_ID]); +- flower->mask.vlan_id[0] = 0xffff; ++ flower->mask.vlan_id[0] = VLAN_VID_MASK >> VLAN_VID_SHIFT; + } + if (attrs[TCA_FLOWER_KEY_VLAN_PRIO]) { + flower->key.vlan_prio[0] = + nl_attr_get_u8(attrs[TCA_FLOWER_KEY_VLAN_PRIO]); +- flower->mask.vlan_prio[0] = 0xff; ++ flower->mask.vlan_prio[0] = VLAN_PCP_MASK >> VLAN_PCP_SHIFT; + } + + if (!attrs[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) { +@@ -566,17 +567,18 @@ nl_parse_flower_vlan(struct nlattr **attrs, struct tc_flower *flower) + } + + flower->key.encap_eth_type[1] = flower->key.encap_eth_type[0]; ++ flower->mask.encap_eth_type[1] = CONSTANT_HTONS(0xffff); + flower->key.encap_eth_type[0] = encap_ethtype; + + if (attrs[TCA_FLOWER_KEY_CVLAN_ID]) { + flower->key.vlan_id[1] = + nl_attr_get_u16(attrs[TCA_FLOWER_KEY_CVLAN_ID]); +- flower->mask.vlan_id[1] = 0xffff; ++ flower->mask.vlan_id[1] = VLAN_VID_MASK >> VLAN_VID_SHIFT; + } + if (attrs[TCA_FLOWER_KEY_CVLAN_PRIO]) { + flower->key.vlan_prio[1] = + nl_attr_get_u8(attrs[TCA_FLOWER_KEY_CVLAN_PRIO]); +- flower->mask.vlan_prio[1] = 0xff; ++ flower->mask.vlan_prio[1] = VLAN_PCP_MASK >> VLAN_PCP_SHIFT; + } + } + +@@ -956,14 +958,14 @@ static const struct nl_policy pedit_policy[] = { + static int + nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) + { +- struct tc_action *action; ++ struct tc_action *action = &flower->actions[flower->action_count++]; + struct nlattr *pe_attrs[ARRAY_SIZE(pedit_policy)]; + const struct tc_pedit *pe; + const struct tc_pedit_key *keys; + const struct nlattr *nla, *keys_ex, *ex_type; + const void *keys_attr; +- char *rewrite_key = (void *) &flower->rewrite.key; +- char *rewrite_mask = (void *) &flower->rewrite.mask; ++ char *rewrite_key = (void *) &action->rewrite.key; ++ char *rewrite_mask = (void *) &action->rewrite.mask; + size_t keys_ex_size, left; + int type, i = 0, err; + +@@ -1042,7 +1044,6 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) + i++; + } + +- action = &flower->actions[flower->action_count++]; + action->type = TC_ACT_PEDIT; + + return 0; +@@ -1437,7 +1438,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) + if (ipv4_max) { + ovs_be32 addr = nl_attr_get_be32(ipv4_max); + +- action->ct.range.ipv4.max = addr; ++ if (action->ct.range.ipv4.min != addr) { ++ action->ct.range.ipv4.max = addr; ++ } + } + } else if (ipv6_min) { + action->ct.range.ip_family = AF_INET6; +@@ -1446,7 +1449,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) + if (ipv6_max) { + struct in6_addr addr = nl_attr_get_in6_addr(ipv6_max); + +- action->ct.range.ipv6.max = addr; ++ if (!ipv6_addr_equals(&action->ct.range.ipv6.min, &addr)) { ++ action->ct.range.ipv6.max = addr; ++ } + } + } + +@@ -1454,6 +1459,10 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) + action->ct.range.port.min = nl_attr_get_be16(port_min); + if (port_max) { + action->ct.range.port.max = nl_attr_get_be16(port_max); ++ if (action->ct.range.port.min == ++ action->ct.range.port.max) { ++ action->ct.range.port.max = 0; ++ } + } + } + } +@@ -1652,6 +1661,9 @@ static const struct nl_policy stats_policy[] = { [TCA_STATS_BASIC] = { .type = NL_A_UNSPEC, .min_len = sizeof(struct gnet_stats_basic), .optional = false, }, @@ -22267,7 +22463,7 @@ index 3192207984..57c30ed290 100644 }; static int -@@ -1664,8 +1667,11 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, +@@ -1664,8 +1676,11 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, const char *act_kind; struct nlattr *action_attrs[ARRAY_SIZE(act_policy)]; struct nlattr *stats_attrs[ARRAY_SIZE(stats_policy)]; @@ -22281,7 +22477,7 @@ index 3192207984..57c30ed290 100644 int err = 0; if (!nl_parse_nested(action, act_policy, action_attrs, -@@ -1721,10 +1727,26 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, +@@ -1721,10 +1736,26 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, return EPROTO; } @@ -22312,7 +22508,44 @@ index 3192207984..57c30ed290 100644 } return 0; -@@ -2464,6 +2486,17 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, +@@ -2318,14 +2349,14 @@ nl_msg_put_act_flags(struct ofpbuf *request) { + * first_word_mask/last_word_mask - the mask to use for the first/last read + * (as we read entire words). */ + static void +-calc_offsets(struct tc_flower *flower, struct flower_key_to_pedit *m, ++calc_offsets(struct tc_action *action, struct flower_key_to_pedit *m, + int *cur_offset, int *cnt, ovs_be32 *last_word_mask, + ovs_be32 *first_word_mask, ovs_be32 **mask, ovs_be32 **data) + { + int start_offset, max_offset, total_size; + int diff, right_zero_bits, left_zero_bits; +- char *rewrite_key = (void *) &flower->rewrite.key; +- char *rewrite_mask = (void *) &flower->rewrite.mask; ++ char *rewrite_key = (void *) &action->rewrite.key; ++ char *rewrite_mask = (void *) &action->rewrite.mask; + + max_offset = m->offset + m->size; + start_offset = ROUND_DOWN(m->offset, 4); +@@ -2392,7 +2423,8 @@ csum_update_flag(struct tc_flower *flower, + + static int + nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, +- struct tc_flower *flower) ++ struct tc_flower *flower, ++ struct tc_action *action) + { + struct { + struct tc_pedit sel; +@@ -2416,7 +2448,7 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, + continue; + } + +- calc_offsets(flower, m, &cur_offset, &cnt, &last_word_mask, ++ calc_offsets(action, m, &cur_offset, &cnt, &last_word_mask, + &first_word_mask, &mask, &data); + + for (j = 0; j < cnt; j++, mask++, data++, cur_offset += 4) { +@@ -2464,6 +2496,40 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, return 0; } @@ -22327,10 +22560,59 @@ index 3192207984..57c30ed290 100644 + nl_msg_end_nested(request, act_offset); +} + ++/* Aggregates all previous successive pedit actions csum_update_flags ++ * to flower->csum_update_flags. Only append one csum action to the ++ * last pedit action. */ ++static void ++nl_msg_put_csum_act(struct ofpbuf *request, struct tc_flower *flower, ++ uint16_t *act_index) ++{ ++ size_t act_offset; ++ ++ /* No pedit actions or processed already. */ ++ if (!flower->csum_update_flags) { ++ return; ++ } ++ ++ act_offset = nl_msg_start_nested(request, (*act_index)++); ++ nl_msg_put_act_csum(request, flower->csum_update_flags); ++ nl_msg_put_act_flags(request); ++ nl_msg_end_nested(request, act_offset); ++ ++ /* Clear it. So we can have another series of pedit actions. */ ++ flower->csum_update_flags = 0; ++} ++ static int nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) { -@@ -2498,6 +2531,11 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) +@@ -2480,24 +2546,31 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) + + action = flower->actions; + for (i = 0; i < flower->action_count; i++, action++) { ++ if (action->type != TC_ACT_PEDIT) { ++ nl_msg_put_csum_act(request, flower, &act_index); ++ } + switch (action->type) { + case TC_ACT_PEDIT: { + act_offset = nl_msg_start_nested(request, act_index++); +- error = nl_msg_put_flower_rewrite_pedits(request, flower); ++ error = nl_msg_put_flower_rewrite_pedits(request, flower, ++ action); + if (error) { + return error; + } + nl_msg_end_nested(request, act_offset); + +- if (flower->csum_update_flags) { +- act_offset = nl_msg_start_nested(request, act_index++); +- nl_msg_put_act_csum(request, flower->csum_update_flags); +- nl_msg_put_act_flags(request); +- nl_msg_end_nested(request, act_offset); ++ if (i == flower->action_count - 1) { ++ /* If this is the last action check csum calc again. */ ++ nl_msg_put_csum_act(request, flower, &act_index); + } } break; case TC_ACT_ENCAP: { @@ -22342,7 +22624,7 @@ index 3192207984..57c30ed290 100644 act_offset = nl_msg_start_nested(request, act_index++); nl_msg_put_act_tunnel_key_set(request, action->encap.id_present, action->encap.id, -@@ -2555,9 +2593,7 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) +@@ -2555,9 +2628,7 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) break; case TC_ACT_OUTPUT: { if (!released && flower->tunnel) { @@ -22353,16 +22635,102 @@ index 3192207984..57c30ed290 100644 released = true; } -@@ -2892,6 +2928,50 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) +@@ -2813,13 +2884,13 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) + FLOWER_PUT_MASKED_VALUE(sctp_src, TCA_FLOWER_KEY_SCTP_SRC); + FLOWER_PUT_MASKED_VALUE(sctp_dst, TCA_FLOWER_KEY_SCTP_DST); + } +- +- 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_mark, TCA_FLOWER_KEY_CT_MARK); +- FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS); + } + ++ 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_mark, TCA_FLOWER_KEY_CT_MARK); ++ FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS); ++ + if (host_eth_type == ETH_P_IP) { + FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_src, TCA_FLOWER_KEY_IPV4_SRC); + FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_dst, TCA_FLOWER_KEY_IPV4_DST); +@@ -2892,6 +2963,118 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) return 0; } ++static void ++log_tc_flower_match(const char *msg, ++ const struct tc_flower *a, ++ const struct tc_flower *b) ++{ ++ uint8_t key_a[sizeof(struct tc_flower_key)]; ++ uint8_t key_b[sizeof(struct tc_flower_key)]; ++ struct ds s = DS_EMPTY_INITIALIZER; ++ ++ for (int i = 0; i < sizeof a->key; i++) { ++ uint8_t mask_a = ((uint8_t *) &a->mask)[i]; ++ uint8_t mask_b = ((uint8_t *) &b->mask)[i]; ++ ++ key_a[i] = ((uint8_t *) &a->key)[i] & mask_a; ++ key_b[i] = ((uint8_t *) &b->key)[i] & mask_b; ++ } ++ ds_put_cstr(&s, "\nExpected Mask:\n"); ++ ds_put_hex(&s, &a->mask, sizeof a->mask); ++ ds_put_cstr(&s, "\nReceived Mask:\n"); ++ ds_put_hex(&s, &b->mask, sizeof b->mask); ++ ds_put_cstr(&s, "\nExpected Key:\n"); ++ ds_put_hex(&s, &a->key, sizeof a->key); ++ ds_put_cstr(&s, "\nReceived Key:\n"); ++ ds_put_hex(&s, &b->key, sizeof b->key); ++ ds_put_cstr(&s, "\nExpected Masked Key:\n"); ++ ds_put_hex(&s, key_a, sizeof key_a); ++ ds_put_cstr(&s, "\nReceived Masked Key:\n"); ++ ds_put_hex(&s, key_b, sizeof key_b); ++ ++ if (a->action_count != b->action_count) { ++ /* If action count is not equal, we print all actions to see which ++ * ones are missing. */ ++ const struct tc_action *action; ++ int i; ++ ++ ds_put_cstr(&s, "\nExpected Actions:\n"); ++ for (i = 0, action = a->actions; i < a->action_count; i++, action++) { ++ ds_put_cstr(&s, " - "); ++ ds_put_hex(&s, action, sizeof *action); ++ ds_put_cstr(&s, "\n"); ++ } ++ ds_put_cstr(&s, "Received Actions:\n"); ++ for (i = 0, action = b->actions; i < b->action_count; i++, action++) { ++ ds_put_cstr(&s, " - "); ++ ds_put_hex(&s, action, sizeof *action); ++ ds_put_cstr(&s, "\n"); ++ } ++ } else { ++ /* Only dump the delta in actions. */ ++ const struct tc_action *action_a = a->actions; ++ const struct tc_action *action_b = b->actions; ++ ++ for (int i = 0; i < a->action_count; i++, action_a++, action_b++) { ++ if (memcmp(action_a, action_b, sizeof *action_a)) { ++ ds_put_format(&s, ++ "\nAction %d mismatch:\n - Expected Action: ", ++ i); ++ ds_put_hex(&s, action_a, sizeof *action_a); ++ ds_put_cstr(&s, "\n - Received Action: "); ++ ds_put_hex(&s, action_b, sizeof *action_b); ++ } ++ } ++ } ++ VLOG_DBG_RL(&error_rl, "%s%s", msg, ds_cstr(&s)); ++ ds_destroy(&s); ++} ++ +static bool +cmp_tc_flower_match_action(const struct tc_flower *a, + const struct tc_flower *b) +{ + if (memcmp(&a->mask, &b->mask, sizeof a->mask)) { -+ VLOG_DBG_RL(&error_rl, "tc flower compare failed mask compare"); ++ log_tc_flower_match("tc flower compare failed mask compare:", a, b); + return false; + } + @@ -22375,8 +22743,8 @@ index 3192207984..57c30ed290 100644 + uint8_t key_b = ((uint8_t *)&b->key)[i] & mask; + + if (key_a != key_b) { -+ VLOG_DBG_RL(&error_rl, "tc flower compare failed key compare at " -+ "%d", i); ++ log_tc_flower_match("tc flower compare failed masked key compare:", ++ a, b); + return false; + } + } @@ -22386,14 +22754,15 @@ index 3192207984..57c30ed290 100644 + const struct tc_action *action_b = b->actions; + + if (a->action_count != b->action_count) { -+ VLOG_DBG_RL(&error_rl, "tc flower compare failed action length check"); ++ log_tc_flower_match("tc flower compare failed action length check", ++ a, b); + return false; + } + + for (int i = 0; i < a->action_count; i++, action_a++, action_b++) { + if (memcmp(action_a, action_b, sizeof *action_a)) { -+ VLOG_DBG_RL(&error_rl, "tc flower compare failed action compare " -+ "for %d", i); ++ log_tc_flower_match("tc flower compare failed action compare", ++ a, b); + return false; + } + } @@ -22404,7 +22773,7 @@ index 3192207984..57c30ed290 100644 int tc_replace_flower(struct tcf_id *id, struct tc_flower *flower) { -@@ -2923,6 +3003,21 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower *flower) +@@ -2923,6 +3106,21 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower *flower) id->prio = tc_get_major(tc->tcm_info); id->handle = tc->tcm_handle; @@ -22427,10 +22796,34 @@ index 3192207984..57c30ed290 100644 } diff --git a/lib/tc.h b/lib/tc.h -index 281231c0d3..7b833186eb 100644 +index 281231c0d3..5bee1a36c2 100644 --- a/lib/tc.h +++ b/lib/tc.h -@@ -327,7 +327,8 @@ struct tc_flower { +@@ -253,11 +253,23 @@ struct tc_action { + bool force; + bool commit; + } ct; ++ ++ struct { ++ struct tc_flower_key key; ++ struct tc_flower_key mask; ++ } rewrite; + }; + + enum tc_action_type type; + }; + ++/* assert that if we overflow with a masked write of uint32_t to the last byte ++ * of action.rewrite we overflow inside struct tc_action. ++ * shouldn't happen unless someone moves rewrite to the end of action */ ++BUILD_ASSERT_DECL(offsetof(struct tc_action, rewrite) ++ + MEMBER_SIZEOF(struct tc_action, rewrite) ++ + sizeof(uint32_t) - 2 < sizeof(struct tc_action)); ++ + enum tc_offloaded_state { + TC_OFFLOADED_STATE_UNDEFINED, + TC_OFFLOADED_STATE_IN_HW, +@@ -327,15 +339,10 @@ struct tc_flower { int action_count; struct tc_action actions[TCA_ACT_MAX_NUM]; @@ -22439,7 +22832,29 @@ index 281231c0d3..7b833186eb 100644 + struct ovs_flow_stats stats_hw; uint64_t lastused; - struct { +- struct { +- bool rewrite; +- struct tc_flower_key key; +- struct tc_flower_key mask; +- } rewrite; +- + uint32_t csum_update_flags; + + bool tunnel; +@@ -349,13 +356,6 @@ struct tc_flower { + enum tc_offload_policy tc_policy; + }; + +-/* assert that if we overflow with a masked write of uint32_t to the last byte +- * of flower.rewrite we overflow inside struct flower. +- * shouldn't happen unless someone moves rewrite to the end of flower */ +-BUILD_ASSERT_DECL(offsetof(struct tc_flower, rewrite) +- + MEMBER_SIZEOF(struct tc_flower, rewrite) +- + sizeof(uint32_t) - 2 < sizeof(struct tc_flower)); +- + int tc_replace_flower(struct tcf_id *id, struct tc_flower *flower); + int tc_del_filter(struct tcf_id *id); + int tc_get_flower(struct tcf_id *id, struct tc_flower *flower); diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c index 5bda4af7e0..995c88bf17 100644 --- a/lib/tnl-neigh-cache.c @@ -28563,6 +28978,19 @@ index 48c5de9d19..6a597488e6 100644 AT_SETUP([tunnel_push_pop - underlay bridge match]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) +diff --git a/tests/tunnel.at b/tests/tunnel.at +index b8ae7caa9b..fd482aa872 100644 +--- a/tests/tunnel.at ++++ b/tests/tunnel.at +@@ -126,7 +126,7 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl + AT_CHECK([ovs-appctl dpctl/add-flow "tunnel(dst=1.1.1.1,src=3.3.3.200/255.255.255.0,tp_dst=123,tp_src=1,ttl=64),recirc_id(0),in_port(1),eth(),eth_type(0x0800),ipv4()" "2"]) + + AT_CHECK([ovs-appctl dpctl/dump-flows | tail -1], [0], [dnl +-tunnel(src=3.3.3.200/255.255.255.0,dst=1.1.1.1,ttl=64,tp_src=1,tp_dst=123),recirc_id(0),in_port(1),eth_type(0x0800), packets:0, bytes:0, used:never, actions:2 ++tunnel(src=3.3.3.200/255.255.255.0,dst=1.1.1.1,ttl=64,tp_src=1,tp_dst=123),recirc_id(0),in_port(1),eth(),eth_type(0x0800), packets:0, bytes:0, used:never, actions:2 + ]) + + OVS_VSWITCHD_STOP diff --git a/utilities/automake.mk b/utilities/automake.mk index e2e22c39ae..f7aa1418d8 100644 --- a/utilities/automake.mk diff --git a/SPECS/openvswitch2.15.spec b/SPECS/openvswitch2.15.spec index c621be1..f3c2aa2 100644 --- a/SPECS/openvswitch2.15.spec +++ b/SPECS/openvswitch2.15.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.15.0 -Release: 84%{?dist} +Release: 85%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -702,6 +702,18 @@ exit 0 %endif %changelog +* Mon Mar 21 2022 Open vSwitch CI - 2.15.0-85 +- Merging upstream branch-2.15 [RH git: 7b1d494b1f] + Commit list: + c804df6e11 odp-util: Fix output for tc to be equal to kernel. + 92207b062a netdev-offload-tc: Fix IP and port ranges in flower returns. + 743974a961 netdev-offload-tc: Always include conntrack information to tc. + 0ea2fa78e3 netdev-offload-tc: Check for valid netdev ifindex in flow_put. + e832fa9b12 netdev-offload-tc: Set the correct VLAN_VID and VLAN_PCP masks. + 7dace029e8 netdev-offload-tc: Add debug logs on tc rule verify failures. + 56ee5f7070 tc: Keep header rewrite actions order. + + * Fri Mar 18 2022 Open vSwitch CI - 2.15.0-84 - Merging upstream branch-2.15 [RH git: 137641442f] Commit list: