From cc3329be23902a2ea75b38032187579b209cb95c Mon Sep 17 00:00:00 2001 From: Open vSwitch CI Date: Dec 06 2021 19:35:30 +0000 Subject: Import openvswitch2.16-2.16.0-33 from Fast DataPath --- diff --git a/SOURCES/openvswitch-2.16.0.patch b/SOURCES/openvswitch-2.16.0.patch index a2b6e28..a9758fe 100644 --- a/SOURCES/openvswitch-2.16.0.patch +++ b/SOURCES/openvswitch-2.16.0.patch @@ -64,6 +64,34 @@ index 51d0511080..c7aeede06e 100644 - python3-pip - python3-sphinx - libelf-dev +diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst +index 68c9867b19..64bc577e0b 100644 +--- a/Documentation/faq/releases.rst ++++ b/Documentation/faq/releases.rst +@@ -205,8 +205,8 @@ Q: What DPDK version does each Open vSwitch release work with? + 2.10.x 17.11.10 + 2.11.x 18.11.9 + 2.12.x 18.11.9 +- 2.13.x 19.11.8 +- 2.14.x 19.11.8 ++ 2.13.x 19.11.10 ++ 2.14.x 19.11.10 + 2.15.x 20.11.1 + 2.16.x 20.11.1 + ============ ======== +diff --git a/Documentation/intro/install/dpdk.rst b/Documentation/intro/install/dpdk.rst +index d8fa931fab..1dbead3276 100644 +--- a/Documentation/intro/install/dpdk.rst ++++ b/Documentation/intro/install/dpdk.rst +@@ -219,7 +219,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:: + diff --git a/NEWS b/NEWS index 559a51ba3f..139c24a4f8 100644 --- a/NEWS @@ -758,6 +786,37 @@ index 34fc042373..5f4b60c5a6 100644 ofpbuf_delete(buf); if (create) { +diff --git a/lib/flow.c b/lib/flow.c +index 89837de95d..a021bc0eba 100644 +--- a/lib/flow.c ++++ b/lib/flow.c +@@ -1006,14 +1006,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 d9f781147a..507db2aea2 100644 --- a/lib/ipf.c @@ -1946,6 +2005,224 @@ index a426fcfeb6..970f78bb52 100644 break; } } +diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h +index 57c7d17cb2..14b909973d 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 bd6103b1c8..56aeac7209 100644 +--- a/ofproto/ofproto.c ++++ b/ofproto/ofproto.c +@@ -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); +@@ -1631,6 +1635,7 @@ ofproto_flush__(struct ofproto *ofproto, bool del) + } + 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'. */ +@@ -1682,6 +1687,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); + } + +@@ -1878,6 +1888,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; + } + +@@ -4437,6 +4450,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) +@@ -5833,7 +5860,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; +@@ -5941,7 +5968,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); + } +@@ -7967,6 +7994,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; + +@@ -8104,6 +8132,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. +@@ -8165,6 +8220,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 +@@ -8173,6 +8232,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(); +@@ -8183,6 +8245,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); +@@ -8191,14 +8256,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/file.c b/ovsdb/file.c index 59220824fa..9f44007d97 100644 --- a/ovsdb/file.c @@ -4092,11 +4369,98 @@ index f5a520862c..ac5b0fd0c6 100644 +if ssl: # Register SSL only if the OpenSSL module is available Stream.register_method("ssl", SSLStream) +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/ofproto-dpif.at b/tests/ofproto-dpif.at -index 956a69e1fa..0c127a6474 100644 +index 956a69e1fa..035321e892 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at -@@ -9695,6 +9695,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2): +@@ -4862,6 +4862,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 +@@ -9695,6 +9743,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2): OVS_VSWITCHD_STOP AT_CLEANUP @@ -4123,7 +4487,7 @@ index 956a69e1fa..0c127a6474 100644 AT_SETUP([ofproto-dpif - ICMPv6]) OVS_VSWITCHD_START add_of_ports br0 1 -@@ -11404,6 +11424,23 @@ Megaflow: recirc_id=0x3,eth,ip,in_port=1,nw_frag=no +@@ -11404,6 +11472,23 @@ Megaflow: recirc_id=0x3,eth,ip,in_port=1,nw_frag=no Datapath actions: 4 ]) @@ -4699,6 +5063,45 @@ index 71800795c0..e6e07f4763 100644 --no-full-hostname set short hostname instead of full hostname --no-record-hostname do not attempt to determine/record system hostname as part of start command +diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in +index 3eda01d3c1..13477a6a9e 100644 +--- a/utilities/ovs-lib.in ++++ b/utilities/ovs-lib.in +@@ -519,13 +519,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-save b/utilities/ovs-save +index 27ce3a9aad..fb2025b765 100755 +--- a/utilities/ovs-save ++++ b/utilities/ovs-save +@@ -150,7 +150,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/vswitchd/bridge.c b/vswitchd/bridge.c index cb7c5cb769..c790a56adf 100644 --- a/vswitchd/bridge.c diff --git a/SPECS/openvswitch2.16.spec b/SPECS/openvswitch2.16.spec index 5d4d334..b2851c7 100644 --- a/SPECS/openvswitch2.16.spec +++ b/SPECS/openvswitch2.16.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.16.0 -Release: 32%{?dist} +Release: 33%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -699,6 +699,20 @@ exit 0 %endif %changelog +* Mon Dec 06 2021 Open vSwitch CI - 2.16.0-33 +- Merging upstream branch-2.16 [RH git: 8708b55152] + Commit list: + 3e527f21cf flow: Consider dataofs when parsing TCP packets. + b537e049ad tests/flowgen: Fix packet data endianness. + 35244b4980 ofproto: Fix resource usage explosion due to removal of large number of flows. + a201297639 ofproto: Fix resource usage explosion while processing bundled FLOW_MOD. + cd0133402c tests/flowgen: Fix length field of 802.2 data link header. + 2d65b8ffd2 ovs-lib: Backup and remove existing DB when joining cluster. + ab01177637 docs/dpdk: Fix install doc. + 38a2129524 ovs-save: Save igmp flows in ofp_parse syntax. + dc77857ce2 faq: Update OVS/DPDK version table for OVS 2.13/2.14. + + * Thu Nov 18 2021 Open vSwitch CI - 2.16.0-32 - Merging upstream branch-2.16 [RH git: e90e06a818] Commit list: