diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch index 4540f0c..4b78693 100644 --- a/SOURCES/openvswitch-2.13.0.patch +++ b/SOURCES/openvswitch-2.13.0.patch @@ -1,6 +1,6 @@ diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh new file mode 100755 -index 0000000000..b22ad95310 +index 0000000000..1784878962 --- /dev/null +++ b/.ci/linux-build.sh @@ -0,0 +1,244 @@ @@ -188,7 +188,7 @@ index 0000000000..b22ad95310 + +if [ "$DPDK" ] || [ "$DPDK_SHARED" ]; then + if [ -z "$DPDK_VER" ]; then -+ DPDK_VER="19.11.8" ++ DPDK_VER="19.11.10" + fi + install_dpdk $DPDK_VER + # Enable pdump support in OVS. @@ -649,7 +649,7 @@ index 22976a3cd6..f46ec988a3 100644 else install-man-rst: diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst -index 6702c58a2b..70a0e9b221 100644 +index 6702c58a2b..0df2e4163e 100644 --- a/Documentation/faq/releases.rst +++ b/Documentation/faq/releases.rst @@ -67,9 +67,10 @@ Q: What Linux kernel versions does each Open vSwitch release work with? @@ -702,7 +702,7 @@ index 6702c58a2b..70a0e9b221 100644 + 2.10.x 17.11.10 + 2.11.x 18.11.11 + 2.12.x 18.11.11 -+ 2.13.x 19.11.8 ++ 2.13.x 19.11.10 + ============ ======== Q: Are all the DPDK releases that OVS versions work with maintained? @@ -727,7 +727,7 @@ index 5a314cc60a..f2039595e7 100644 Email Subject ------------- diff --git a/Documentation/intro/install/dpdk.rst b/Documentation/intro/install/dpdk.rst -index dbf88ec43f..b603b6f0b0 100644 +index dbf88ec43f..7acdaac06b 100644 --- a/Documentation/intro/install/dpdk.rst +++ b/Documentation/intro/install/dpdk.rst @@ -42,7 +42,7 @@ Build requirements @@ -735,7 +735,7 @@ index dbf88ec43f..b603b6f0b0 100644 vSwitch with DPDK will require the following: -- DPDK 19.11 -+- DPDK 19.11.8 ++- DPDK 19.11.10 - A `DPDK supported NIC`_ @@ -746,12 +746,21 @@ index dbf88ec43f..b603b6f0b0 100644 - $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz - $ tar xf dpdk-19.11.tar.xz - $ export DPDK_DIR=/usr/src/dpdk-19.11 -+ $ wget https://fast.dpdk.org/rel/dpdk-19.11.8.tar.xz -+ $ tar xf dpdk-19.11.8.tar.xz -+ $ export DPDK_DIR=/usr/src/dpdk-stable-19.11.8 ++ $ wget https://fast.dpdk.org/rel/dpdk-19.11.10.tar.xz ++ $ tar xf dpdk-19.11.10.tar.xz ++ $ export DPDK_DIR=/usr/src/dpdk-stable-19.11.10 $ cd $DPDK_DIR #. (Optional) Configure DPDK as a shared library +@@ -170,7 +170,7 @@ To verify hugepage configuration:: + + Mount the hugepages, if not already mounted by default:: + +- $ mount -t hugetlbfs none /dev/hugepages`` ++ $ mount -t hugetlbfs none /dev/hugepages + + .. note:: + @@ -687,6 +687,15 @@ Limitations around is temporary and is expected to be removed once a method is provided by DPDK to query the upper bound MTU value for a given device. @@ -832,7 +841,7 @@ index 103495415a..a98ec672fc 100644 This configuration accomplishes that the high priority traffic has a guaranteed bandwidth egressing the ports at CIR (1000pps), but it can also diff --git a/Documentation/topics/dpdk/vhost-user.rst b/Documentation/topics/dpdk/vhost-user.rst -index c6c6fd8bde..b10daa53e3 100644 +index c6c6fd8bde..14b32ab3b8 100644 --- a/Documentation/topics/dpdk/vhost-user.rst +++ b/Documentation/topics/dpdk/vhost-user.rst @@ -392,9 +392,9 @@ To begin, instantiate a guest as described in :ref:`dpdk-vhost-user` or @@ -842,9 +851,9 @@ index c6c6fd8bde..b10daa53e3 100644 - $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz - $ tar xf dpdk-19.11.tar.xz - $ export DPDK_DIR=/root/dpdk/dpdk-19.11 -+ $ wget https://fast.dpdk.org/rel/dpdk-19.11.8.tar.xz -+ $ tar xf dpdk-19.11.8.tar.xz -+ $ export DPDK_DIR=/root/dpdk/dpdk-stable-19.11.8 ++ $ wget https://fast.dpdk.org/rel/dpdk-19.11.10.tar.xz ++ $ tar xf dpdk-19.11.10.tar.xz ++ $ export DPDK_DIR=/root/dpdk/dpdk-stable-19.11.10 $ export DPDK_TARGET=x86_64-native-linuxapp-gcc $ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET $ cd $DPDK_DIR @@ -987,12 +996,15 @@ index b279303d18..b3b56cd50e 100644 boot.sh \ poc/builders/Vagrantfile \ diff --git a/NEWS b/NEWS -index dab94e924d..8409097356 100644 +index dab94e924d..a637489365 100644 --- a/NEWS +++ b/NEWS -@@ -1,3 +1,60 @@ +@@ -1,3 +1,63 @@ +v2.13.6 - xx xxx xxxx +--------------------- ++ - DPDK: ++ * OVS validated with DPDK 19.11.10. It is recommended to use this version ++ until further releases. + +v2.13.5 - 21 Oct 2021 +--------------------- @@ -1051,7 +1063,7 @@ index dab94e924d..8409097356 100644 v2.13.0 - 14 Feb 2020 --------------------- - OVN: -@@ -43,6 +100,9 @@ v2.13.0 - 14 Feb 2020 +@@ -43,6 +103,9 @@ v2.13.0 - 14 Feb 2020 - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and type filter supports new filters: "dpdk" and "partially-offloaded". @@ -1061,7 +1073,7 @@ index dab94e924d..8409097356 100644 v2.12.0 - 03 Sep 2019 --------------------- -@@ -117,9 +177,6 @@ v2.12.0 - 03 Sep 2019 +@@ -117,9 +180,6 @@ v2.12.0 - 03 Sep 2019 * Add support for conntrack zone-based timeout policy. - 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows. 'ovs-appctl dpctl/dump-flows' should be used instead. @@ -81911,7 +81923,7 @@ index 6f7b610a99..fd0127ed17 100644 dst->allocated = dst->length; dst->string = xmalloc(dst->allocated + 1); diff --git a/lib/flow.c b/lib/flow.c -index 45bb96b543..353d5cd3ed 100644 +index 45bb96b543..f3f0358b36 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -655,7 +655,7 @@ ipv4_sanity_check(const struct ip_header *nh, size_t size, @@ -81934,6 +81946,33 @@ index 45bb96b543..353d5cd3ed 100644 return false; } +@@ -970,14 +970,18 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) + if (OVS_LIKELY(nw_proto == IPPROTO_TCP)) { + if (OVS_LIKELY(size >= TCP_HEADER_LEN)) { + const struct tcp_header *tcp = data; +- +- miniflow_push_be32(mf, arp_tha.ea[2], 0); +- miniflow_push_be32(mf, tcp_flags, +- TCP_FLAGS_BE32(tcp->tcp_ctl)); +- miniflow_push_be16(mf, tp_src, tcp->tcp_src); +- miniflow_push_be16(mf, tp_dst, tcp->tcp_dst); +- miniflow_push_be16(mf, ct_tp_src, ct_tp_src); +- miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst); ++ size_t tcp_hdr_len = TCP_OFFSET(tcp->tcp_ctl) * 4; ++ ++ if (OVS_LIKELY(tcp_hdr_len >= TCP_HEADER_LEN) ++ && OVS_LIKELY(size >= tcp_hdr_len)) { ++ miniflow_push_be32(mf, arp_tha.ea[2], 0); ++ miniflow_push_be32(mf, tcp_flags, ++ TCP_FLAGS_BE32(tcp->tcp_ctl)); ++ miniflow_push_be16(mf, tp_src, tcp->tcp_src); ++ miniflow_push_be16(mf, tp_dst, tcp->tcp_dst); ++ miniflow_push_be16(mf, ct_tp_src, ct_tp_src); ++ miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst); ++ } + } + } else if (OVS_LIKELY(nw_proto == IPPROTO_UDP)) { + if (OVS_LIKELY(size >= UDP_HEADER_LEN)) { diff --git a/lib/ipf.c b/lib/ipf.c index 446e89d13c..009f5d1e9b 100644 --- a/lib/ipf.c @@ -85879,11 +85918,59 @@ index c9d5df34b0..4d1f126910 100644 /* Stores the various features which the corresponding backer supports. */ +diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h +index afecb24cba..dab7b37fe0 100644 +--- a/ofproto/ofproto-provider.h ++++ b/ofproto/ofproto-provider.h +@@ -66,6 +66,7 @@ struct bfd_cfg; + struct meter; + struct ofoperation; + struct ofproto_packet_out; ++struct rule_collection; + struct smap; + + extern struct ovs_mutex ofproto_mutex; +@@ -115,6 +116,9 @@ struct ofproto { + /* List of expirable flows, in all flow tables. */ + struct ovs_list expirable OVS_GUARDED_BY(ofproto_mutex); + ++ /* List of flows to remove from flow tables. */ ++ struct rule_collection *to_remove OVS_GUARDED_BY(ofproto_mutex); ++ + /* Meter table. */ + struct ofputil_meter_features meter_features; + struct hmap meters; /* uint32_t indexed 'struct meter *'. */ +@@ -1962,6 +1966,7 @@ struct ofproto_flow_mod { + bool modify_may_add_flow; + bool modify_keep_counts; + enum nx_flow_update_event event; ++ uint8_t table_id; + + /* These are only used during commit execution. + * ofproto_flow_mod_uninit() does NOT clean these up. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c -index 08830d8371..4e9569e4ad 100644 +index 08830d8371..c2d554e46e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c -@@ -961,7 +961,7 @@ ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap) +@@ -213,6 +213,8 @@ static void ofproto_rule_insert__(struct ofproto *, struct rule *) + OVS_REQUIRES(ofproto_mutex); + static void ofproto_rule_remove__(struct ofproto *, struct rule *) + OVS_REQUIRES(ofproto_mutex); ++static void remove_rules_postponed(struct rule_collection *) ++ OVS_REQUIRES(ofproto_mutex); + + /* The source of an OpenFlow request. + * +@@ -530,6 +532,8 @@ ofproto_create(const char *datapath_name, const char *datapath_type, + hindex_init(&ofproto->cookies); + hmap_init(&ofproto->learned_cookies); + ovs_list_init(&ofproto->expirable); ++ ofproto->to_remove = xzalloc(sizeof *ofproto->to_remove); ++ rule_collection_init(ofproto->to_remove); + ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name); + ofproto->min_mtu = INT_MAX; + cmap_init(&ofproto->groups); +@@ -961,7 +965,7 @@ ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap) datapath_type = ofproto_normalize_type(datapath_type); const struct ofproto_class *class = ofproto_class_find__(datapath_type); @@ -85892,7 +85979,7 @@ index 08830d8371..4e9569e4ad 100644 class->get_datapath_cap(datapath_type, dp_cap); } } -@@ -974,7 +974,7 @@ ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, +@@ -974,7 +978,7 @@ ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, datapath_type = ofproto_normalize_type(datapath_type); const struct ofproto_class *class = ofproto_class_find__(datapath_type); @@ -85901,7 +85988,7 @@ index 08830d8371..4e9569e4ad 100644 class->ct_set_zone_timeout_policy(datapath_type, zone_id, timeout_policy); } -@@ -986,7 +986,7 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) +@@ -986,7 +990,7 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) datapath_type = ofproto_normalize_type(datapath_type); const struct ofproto_class *class = ofproto_class_find__(datapath_type); @@ -85910,7 +85997,76 @@ index 08830d8371..4e9569e4ad 100644 class->ct_del_zone_timeout_policy(datapath_type, zone_id); } -@@ -6077,8 +6077,8 @@ ofproto_rule_send_removed(struct rule *rule) +@@ -1635,6 +1639,7 @@ ofproto_flush__(struct ofproto *ofproto) + } + ofproto_group_delete_all__(ofproto); + meter_delete_all(ofproto); ++ remove_rules_postponed(ofproto->to_remove); + /* XXX: Concurrent handler threads may insert new learned flows based on + * learn actions of the now deleted flows right after we release + * 'ofproto_mutex'. */ +@@ -1686,6 +1691,11 @@ ofproto_destroy__(struct ofproto *ofproto) + ovs_assert(hmap_is_empty(&ofproto->learned_cookies)); + hmap_destroy(&ofproto->learned_cookies); + ++ ovs_mutex_lock(&ofproto_mutex); ++ rule_collection_destroy(ofproto->to_remove); ++ free(ofproto->to_remove); ++ ovs_mutex_unlock(&ofproto_mutex); ++ + ofproto->ofproto_class->dealloc(ofproto); + } + +@@ -1882,6 +1892,9 @@ ofproto_run(struct ofproto *p) + + connmgr_run(p->connmgr, handle_openflow); + ++ ovs_mutex_lock(&ofproto_mutex); ++ remove_rules_postponed(p->to_remove); ++ ovs_mutex_unlock(&ofproto_mutex); + return error; + } + +@@ -4440,6 +4453,20 @@ rule_criteria_destroy(struct rule_criteria *criteria) + criteria->version = OVS_VERSION_NOT_REMOVED; /* Mark as destroyed. */ + } + ++/* Adds rules to the 'to_remove' collection, so they can be destroyed ++ * later all together. Destroys 'rules'. */ ++static void ++rules_mark_for_removal(struct ofproto *ofproto, struct rule_collection *rules) ++ OVS_REQUIRES(ofproto_mutex) ++{ ++ struct rule *rule; ++ ++ RULE_COLLECTION_FOR_EACH (rule, rules) { ++ rule_collection_add(ofproto->to_remove, rule); ++ } ++ rule_collection_destroy(rules); ++} ++ + /* Schedules postponed removal of rules, destroys 'rules'. */ + static void + remove_rules_postponed(struct rule_collection *rules) +@@ -5836,7 +5863,7 @@ modify_flows_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, + } + } + learned_cookies_flush(ofproto, &dead_cookies); +- remove_rules_postponed(old_rules); ++ rules_mark_for_removal(ofproto, old_rules); + } + + return error; +@@ -5944,7 +5971,7 @@ delete_flows_finish__(struct ofproto *ofproto, + learned_cookies_dec(ofproto, rule_get_actions(rule), + &dead_cookies); + } +- remove_rules_postponed(rules); ++ rules_mark_for_removal(ofproto, rules); + + learned_cookies_flush(ofproto, &dead_cookies); + } +@@ -6077,8 +6104,8 @@ ofproto_rule_send_removed(struct rule *rule) fr.hard_timeout = rule->hard_timeout; ovs_mutex_unlock(&rule->mutex); rule->ofproto->ofproto_class->rule_get_stats(rule, &stats, &used); @@ -85921,6 +86077,103 @@ index 08830d8371..4e9569e4ad 100644 connmgr_send_flow_removed(connmgr, &fr); ovs_mutex_unlock(&ofproto_mutex); } +@@ -7970,6 +7997,7 @@ ofproto_flow_mod_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, + ofm->criteria.version = OVS_VERSION_NOT_REMOVED; + ofm->conjs = NULL; + ofm->n_conjs = 0; ++ ofm->table_id = fm->table_id; + + bool check_buffer_id = false; + +@@ -8107,6 +8135,33 @@ ofproto_flow_mod_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, + return error; + } + ++static void ++ofproto_table_classifier_defer(struct ofproto *ofproto, ++ const struct ofproto_flow_mod *ofm) ++{ ++ if (check_table_id(ofproto, ofm->table_id)) { ++ if (ofm->table_id == OFPTT_ALL) { ++ struct oftable *table; ++ ++ OFPROTO_FOR_EACH_TABLE (table, ofproto) { ++ classifier_defer(&table->cls); ++ } ++ } else { ++ classifier_defer(&ofproto->tables[ofm->table_id].cls); ++ } ++ } ++} ++ ++static void ++ofproto_publish_classifiers(struct ofproto *ofproto) ++{ ++ struct oftable *table; ++ ++ OFPROTO_FOR_EACH_TABLE (table, ofproto) { ++ classifier_publish(&table->cls); ++ } ++} ++ + /* Commit phases (all while locking ofproto_mutex): + * + * 1. Begin: Gather resources and make changes visible in the next version. +@@ -8168,6 +8223,10 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) + /* Store the version in which the changes should take + * effect. */ + be->ofm.version = version; ++ /* Publishing of the classifier update for every flow ++ * modification in a bundle separately is expensive in ++ * CPU time and memory. Deferring. */ ++ ofproto_table_classifier_defer(ofproto, &be->ofm); + error = ofproto_flow_mod_start(ofproto, &be->ofm); + } else if (be->type == OFPTYPE_GROUP_MOD) { + /* Store the version in which the changes should take +@@ -8176,6 +8235,9 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) + error = ofproto_group_mod_start(ofproto, &be->ogm); + } else if (be->type == OFPTYPE_PACKET_OUT) { + be->opo.version = version; ++ /* Need to use current version of flows for packet-out, ++ * so publishing all classifiers now. */ ++ ofproto_publish_classifiers(ofproto); + error = ofproto_packet_out_start(ofproto, &be->opo); + } else { + OVS_NOT_REACHED(); +@@ -8186,6 +8248,9 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) + } + } + ++ /* Publishing all changes made to classifiers. */ ++ ofproto_publish_classifiers(ofproto); ++ + if (error) { + /* Send error referring to the original message. */ + ofconn_send_error(ofconn, be->msg, error); +@@ -8194,14 +8259,23 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) + /* 2. Revert. Undo all the changes made above. */ + LIST_FOR_EACH_REVERSE_CONTINUE(be, node, &bundle->msg_list) { + if (be->type == OFPTYPE_FLOW_MOD) { ++ /* Publishing of the classifier update for every flow ++ * modification in a bundle separately is expensive in ++ * CPU time and memory. Deferring. */ ++ ofproto_table_classifier_defer(ofproto, &be->ofm); + ofproto_flow_mod_revert(ofproto, &be->ofm); + } else if (be->type == OFPTYPE_GROUP_MOD) { + ofproto_group_mod_revert(ofproto, &be->ogm); + } else if (be->type == OFPTYPE_PACKET_OUT) { ++ /* Need to use current version of flows for packet-out, ++ * so publishing all classifiers now. */ ++ ofproto_publish_classifiers(ofproto); + ofproto_packet_out_revert(ofproto, &be->opo); + } + /* Nothing needs to be reverted for a port mod. */ + } ++ /* Publishing all changes made to classifiers. */ ++ ofproto_publish_classifiers(ofproto); + } else { + /* 4. Finish. */ + LIST_FOR_EACH (be, node, &bundle->msg_list) { diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk index b895f42925..446d6c1362 100644 --- a/ovsdb/automake.mk @@ -88002,6 +88255,38 @@ index 0aeb4e788f..1ec0054c5b 100644 +OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d +/failed to put/d"]) +AT_CLEANUP +diff --git a/tests/flowgen.py b/tests/flowgen.py +index 7ef32d13cb..cb0e9df388 100755 +--- a/tests/flowgen.py ++++ b/tests/flowgen.py +@@ -135,7 +135,7 @@ def output(attrs): + 12893) # urgent pointer + if attrs['TP_PROTO'] == 'TCP+options': + tcp = (tcp[:12] +- + struct.pack('H', (6 << 12) | 0x02 | 0x10) ++ + struct.pack('>H', (6 << 12) | 0x02 | 0x10) + + tcp[14:]) + tcp += struct.pack('>BBH', 2, 4, 1975) # MSS option + tcp += b'payload' +@@ -166,15 +166,15 @@ def output(attrs): + ip = ip[:2] + struct.pack('>H', len(ip)) + ip[4:] + packet += ip + if attrs['DL_HEADER'].startswith('802.2'): +- packet_len = len(packet) ++ packet_len = len(packet) - 14 + if flow['DL_VLAN'] != 0xffff: + packet_len -= 4 + packet = (packet[:len_ofs] + + struct.pack('>H', packet_len) + + packet[len_ofs + 2:]) + +- print(' '.join(['%s=%s' for k, v in attrs.items()])) +- print(' '.join(['%s=%s' for k, v in flow.items()])) ++ print(' '.join(['%s=%s' % (k, v) for k, v in attrs.items()])) ++ print(' '.join(['%s=%s' % (k, v) for k, v in flow.items()])) + print() + + flows.write(struct.pack('>LH', diff --git a/tests/fuzz-regression-list.at b/tests/fuzz-regression-list.at index e3173fb88f..2347c690ef 100644 --- a/tests/fuzz-regression-list.at @@ -88178,10 +88463,65 @@ index 4893280a99..a0487341c9 100644 bad_action 'fin_timeout(foo=bar)' "invalid key 'foo' in 'fin_timeout' argument" diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at -index ff1cc93707..a75388604f 100644 +index ff1cc93707..3e7a626319 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at -@@ -5171,6 +5171,36 @@ AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 2 +@@ -4534,6 +4534,54 @@ recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,fr + OVS_VSWITCHD_STOP + AT_CLEANUP + ++AT_SETUP([ofproto-dpif - handling of malformed TCP packets]) ++OVS_VSWITCHD_START ++add_of_ports br0 1 90 ++ ++dnl drop packet has tcp port 0-f but allow other tcp packets ++AT_DATA([flows.txt], [dnl ++priority=75 tcp tp_dst=0/0xfff0 actions=drop ++priority=50 tcp actions=output:1 ++]) ++AT_CHECK([ovs-ofctl replace-flows br0 flows.txt]) ++ ++dnl good tcp pkt, tcp(sport=100,dpor=16) ++pkt1="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000005002200053330000" ++ ++dnl malformed tcp pkt(tcp_hdr < 20 byte), tcp(sport=100,dport=16,dataofs=1) ++pkt2="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000001002200093330000" ++ ++dnl malformed tcp pkt(tcp_hdr > pkt_len), tcp(sport=100,dport=16,dataofs=15) ++pkt3="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a14141414006400100000000000000000f002200093330000" ++ ++AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg]) ++ ++AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt1"], [0], [stdout]) ++dnl for good tcp pkt, ovs can extract the tp_dst=16 ++AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl ++flow-dump from the main thread: ++recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=16/0xfff0), packets:0, bytes:0, used:never, actions:1 ++]) ++ ++AT_CHECK([ovs-appctl revalidator/purge], [0], [stdout]) ++AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt2"], [0], [stdout]) ++dnl for malformed tcp pkt(tcp_hdr < 20 byte), ovs uses default value tp_dst=0 ++AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl ++flow-dump from the main thread: ++recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=0/0xfff0), packets:0, bytes:0, used:never, actions:drop ++]) ++ ++AT_CHECK([ovs-appctl revalidator/purge], [0], [stdout]) ++AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt3"], [0], [stdout]) ++dnl for malformed tcp pkt(tcp_hdr > pkt_len), ovs uses default value tp_dst=0 ++AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl ++flow-dump from the main thread: ++recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=0/0xfff0), packets:0, bytes:0, used:never, actions:drop ++]) ++ ++OVS_VSWITCHD_STOP ++AT_CLEANUP ++ + AT_SETUP([ofproto-dpif - exit]) + OVS_VSWITCHD_START + add_of_ports br0 1 2 3 10 11 12 13 14 +@@ -5171,6 +5219,36 @@ AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 2 OVS_VSWITCHD_STOP AT_CLEANUP @@ -88218,7 +88558,7 @@ index ff1cc93707..a75388604f 100644 AT_SETUP([ofproto-dpif - debug_slow action]) OVS_VSWITCHD_START -@@ -8632,6 +8662,29 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0c),eth_ty +@@ -8632,6 +8710,29 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0c),eth_ty OVS_VSWITCHD_STOP AT_CLEANUP @@ -88248,7 +88588,7 @@ index ff1cc93707..a75388604f 100644 m4_define([OFPROTO_DPIF_MEGAFLOW_DISABLED], [AT_SETUP([ofproto-dpif megaflow - disabled$1]) OVS_VSWITCHD_START([], [], [], [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])]) -@@ -9215,6 +9268,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2): +@@ -9215,6 +9316,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2): OVS_VSWITCHD_STOP AT_CLEANUP @@ -88275,7 +88615,7 @@ index ff1cc93707..a75388604f 100644 AT_SETUP([ofproto-dpif - ICMPv6]) OVS_VSWITCHD_START add_of_ports br0 1 -@@ -10540,6 +10613,62 @@ udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10. +@@ -10540,6 +10661,62 @@ udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10. OVS_VSWITCHD_STOP AT_CLEANUP @@ -88338,7 +88678,7 @@ index ff1cc93707..a75388604f 100644 AT_SETUP([ofproto-dpif - conntrack - ofproto/trace]) OVS_VSWITCHD_START -@@ -10807,6 +10936,23 @@ Megaflow: recirc_id=0x3,eth,ip,in_port=1,nw_frag=no +@@ -10807,6 +10984,23 @@ Megaflow: recirc_id=0x3,eth,ip,in_port=1,nw_frag=no Datapath actions: 4 ]) @@ -92299,6 +92639,29 @@ index 92d32acb3f..1ece06457c 100644 finally: if local_server is not None: local_server.terminate() +diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in +index d646b444a4..a31b189ceb 100644 +--- a/utilities/ovs-lib.in ++++ b/utilities/ovs-lib.in +@@ -497,13 +497,13 @@ join_cluster() { + LOCAL_ADDR="$3" + REMOTE_ADDR="$4" + +- if test ! -e "$DB_FILE"; then +- ovsdb_tool join-cluster "$DB_FILE" "$SCHEMA_NAME" "$LOCAL_ADDR" "$REMOTE_ADDR" +- elif ovsdb_tool db-is-standalone "$DB_FILE"; then +- # Backup standalone database and join cluster. ++ if test -e "$DB_FILE" && ovsdb_tool db-is-standalone "$DB_FILE"; then + backup_db || return 1 ++ rm $DB_FILE ++ fi ++ if test ! -e "$DB_FILE"; then + action "Joining $DB_FILE to cluster" \ +- ovsdb_tool join-cluster "$DB_FILE" "$SCHEMA_NAME" "$LOCAL_ADDR" ++ ovsdb_tool join-cluster "$DB_FILE" "$SCHEMA_NAME" "$LOCAL_ADDR" "$REMOTE_ADDR" + fi + } + diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 3601890f40..ede7f1e61a 100644 --- a/utilities/ovs-ofctl.c @@ -92412,6 +92775,22 @@ index ee5797221c..a3b6a661de 100755 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. +diff --git a/utilities/ovs-save b/utilities/ovs-save +index 7d810cb40e..a02395be17 100755 +--- a/utilities/ovs-save ++++ b/utilities/ovs-save +@@ -149,7 +149,10 @@ save_flows () { + ovs-ofctl -O $ofp_version dump-flows --no-names --no-stats "$bridge" | \ + sed -e '/NXST_FLOW/d' \ + -e '/OFPST_FLOW/d' \ +- -e 's/\(idle\|hard\)_age=[^,]*,//g' > \ ++ -e 's/\(idle\|hard\)_age=[^,]*,//g' \ ++ -e 's/igmp_type/tp_src/g' \ ++ -e 's/igmp_code/tp_dst/g' \ ++ -e 's/igmp/ip,nw_proto=2/g' > \ + "$workdir/$bridge.flows.dump" + done + echo "rm -rf \"$workdir\"" diff --git a/utilities/ovs-vlan-test.in b/utilities/ovs-vlan-test.in index 154573a9b5..de3ae16862 100755 --- a/utilities/ovs-vlan-test.in diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec index cb58bd7..5de42f9 100644 --- a/SPECS/openvswitch2.13.spec +++ b/SPECS/openvswitch2.13.spec @@ -59,7 +59,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.13.0 -Release: 139%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist} +Release: 140%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -712,6 +712,20 @@ exit 0 %endif %changelog +* Mon Dec 06 2021 Open vSwitch CI - 2.13.0-140 +- Merging upstream branch-2.13 [RH git: 6a59db52e8] + Commit list: + 9fa66631c2 flow: Consider dataofs when parsing TCP packets. + cabeb5d056 tests/flowgen: Fix packet data endianness. + 0b8586fbeb ofproto: Fix resource usage explosion due to removal of large number of flows. + 34801d50e2 ofproto: Fix resource usage explosion while processing bundled FLOW_MOD. + 1910814e5e tests/flowgen: Fix length field of 802.2 data link header. + 6aac7758c0 ovs-lib: Backup and remove existing DB when joining cluster. + a5e1af7b99 docs/dpdk: Fix install doc. + 6fb9d7ab08 ovs-save: Save igmp flows in ofp_parse syntax. + 0c93c71f8c dpdk: Use DPDK 19.11.10 release. + + * Thu Nov 18 2021 Open vSwitch CI - 2.13.0-139 - Merging upstream branch-2.13 [RH git: 37c2767bbd] Commit list: