OVS meters are created in advance and openflow rules refer to them by their unique ID. New tc_police API is used to offload them. By calling the API, police actions are created and meters are mapped to them. These actions then can be used in tc filter rules by the index.
Signed-off-by: Jianbo Liu <[email protected]> --- NEWS | 2 ++ lib/dpif-netlink.c | 31 +++++++++++++++++---- tests/system-offloads-traffic.at | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index eece0d0b2..dfd659d4e 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ Post-v2.17.0 - Windows: * Conntrack support for TCPv6, UDPv6, ICMPv6, FTPv6. * IPv6 Geneve tunnel support. + - Linux datapath: + * Add offloading meter tc police. v2.17.0 - 17 Feb 2022 diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 06e1e8ca0..0af9ee77e 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -4163,11 +4163,18 @@ static int dpif_netlink_meter_set(struct dpif *dpif_, ofproto_meter_id meter_id, struct ofputil_meter_config *config) { + int err; + if (probe_broken_meters(dpif_)) { return ENOMEM; } - return dpif_netlink_meter_set__(dpif_, meter_id, config); + err = dpif_netlink_meter_set__(dpif_, meter_id, config); + if (!err && netdev_is_flow_api_enabled()) { + meter_offload_set(meter_id, config); + } + + return err; } /* Retrieve statistics and/or delete meter 'meter_id'. Statistics are @@ -4258,16 +4265,30 @@ static int dpif_netlink_meter_get(const struct dpif *dpif, ofproto_meter_id meter_id, struct ofputil_meter_stats *stats, uint16_t max_bands) { - return dpif_netlink_meter_get_stats(dpif, meter_id, stats, max_bands, - OVS_METER_CMD_GET); + int err; + + err = dpif_netlink_meter_get_stats(dpif, meter_id, stats, max_bands, + OVS_METER_CMD_GET); + if (!err && netdev_is_flow_api_enabled()) { + meter_offload_get(meter_id, stats, max_bands); + } + + return err; } static int dpif_netlink_meter_del(struct dpif *dpif, ofproto_meter_id meter_id, struct ofputil_meter_stats *stats, uint16_t max_bands) { - return dpif_netlink_meter_get_stats(dpif, meter_id, stats, max_bands, - OVS_METER_CMD_DEL); + int err; + + err = dpif_netlink_meter_get_stats(dpif, meter_id, stats, + max_bands, OVS_METER_CMD_DEL); + if (!err && netdev_is_flow_api_enabled()) { + meter_offload_del(meter_id, stats, max_bands); + } + + return err; } static bool diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at index 80bc1dd5c..7ec75340f 100644 --- a/tests/system-offloads-traffic.at +++ b/tests/system-offloads-traffic.at @@ -168,3 +168,51 @@ matchall ]) OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([offloads - check if meter offloading ]) +AT_KEYWORDS([meter]) +AT_SKIP_IF([test $SUPPORT_TC_INGRESS_PPS = "no"]) +OVS_TRAFFIC_VSWITCHD_START() + +AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true]) +AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=1 pktps bands=type=drop rate=1']) + +ADD_NAMESPACES(at_ns0, at_ns1) +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") + +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0]) +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 "actions=normal"]) +NS_CHECK_EXEC([at_ns0], [ping -q -c 10 -i 0.1 -w 2 10.1.1.2 | FORMAT_PING], [0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +]) + +NETNS_DAEMONIZE([at_ns1], [nc -u -l 5678 > /dev/null ], [nc0.pid]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 del-flows br0]) +AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 "priority=10,in_port=ovs-p0,udp actions=meter:1,normal"]) +AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 "priority=1 actions=normal"]) + +NS_CHECK_EXEC([at_ns0], [sleep 0.5; echo "mark" | nc -u 10.1.1.2 5678 -p 6789]) +AT_CHECK([ovs-appctl dpctl/dump-flows | grep "meter" | DUMP_CLEAN_SORTED], [0], [dnl +in_port(2),eth(macs),eth_type(0x0800),ipv4(proto=17,frag=no), packets:0, bytes:0, used:0.001s, actions:outputmeter(0),3 +]) + +for i in `seq 10`; do +NS_CHECK_EXEC([at_ns0], [echo "mark" | nc -u 10.1.1.2 5678 -p 6789]) +done + +AT_CHECK([ovs-appctl dpctl/dump-flows | grep "meter" | DUMP_CLEAN_SORTED], [0], [dnl +in_port(2),eth(macs),eth_type(0x0800),ipv4(proto=17,frag=no), packets:10, bytes:330, used:0.001s, actions:outputmeter(0),3 +]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | sed -e 's/duration:[[0-9]].[[0-9]]*s/duration:0.001s/'], [0], [dnl +OFPST_METER reply (OF1.3) (xid=0x2): +meter:1 flow_count:1 packet_in_count:11 byte_in_count:377 duration:0.001s bands: +0: packet_count:9 byte_count:0 +]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP -- 2.26.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
