#include "odp-util.h"
#include "util.h"
#include "uuid.h"
@@ -613,6 +614,35 @@ dummy_offload_hw_post_process(const struct dpif_offload
*offload_,
return 0;
}
+static ovs_be16
+dummy_offload_udp_tnl_get_src_port__(const struct dp_packet *packet)
+{
+ /* Use FNV-1a hash to ensure consistent results across all platforms. The
+ * standard OVS hash functions have architecture-specific implementations
+ * (SSE4.2, ARM64 optimizations, etc.) that produce different outputs for
+ * identical inputs, making tests non-deterministic. */
+ const uint8_t *data = dp_packet_data(packet);
+ size_t len = dp_packet_size(packet);
+ uint32_t hash = 2166136261U;
+ uint32_t prime = 16777619U;
+
+ for (size_t i = 0; i < len; i++) {
+ hash ^= data[i];
+ hash *= prime;
+ }
+ return htons((uint16_t) hash);
+}
+
+static bool
+dummy_offload_udp_tnl_get_src_port(
+ const struct dpif_offload *offload OVS_UNUSED,
+ const struct netdev *ingress_netdev OVS_UNUSED,
+ const struct dp_packet *packet, ovs_be16 *src_port)
+{
+ *src_port = dummy_offload_udp_tnl_get_src_port__(packet);
+ return true;
+}
+
static bool
dummy_offload_are_all_actions_supported(const struct dpif_offload *offload_,
odp_port_t in_odp,
@@ -631,7 +661,10 @@ dummy_offload_are_all_actions_supported(const struct
dpif_offload *offload_,
* that they provide full protection when calling netdev_send() from any
* thread, via a netdev-level mutex. */
NL_ATTR_FOR_EACH (nla, left, actions, actions_len) {
- if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) {
+ enum ovs_action_attr action = nl_attr_type(nla);
+
+ switch (action) {
+ case OVS_ACTION_ATTR_OUTPUT: {
odp_port_t out_odp = nl_attr_get_odp_port(nla);
struct dummy_offload_port *out_port;
@@ -641,7 +674,49 @@ dummy_offload_are_all_actions_supported(const struct
dpif_offload *offload_,
netdev_get_type(out_port->pm_port.netdev))) {
return false;
}
- } else {
+ break;
+ }
+
+ case OVS_ACTION_ATTR_TUNNEL_PUSH: {
+ /* We only support UDP tunnels, i.e. VXLAN and Geneve. */
+ const struct ovs_action_push_tnl *data = nl_attr_get(nla);
+
+ if (data->tnl_type != OVS_VPORT_TYPE_VXLAN
+ && data->tnl_type != OVS_VPORT_TYPE_GENEVE) {
+ return false;
+ }
+ break;
+ }
+
+ case OVS_ACTION_ATTR_UNSPEC:
+ case OVS_ACTION_ATTR_USERSPACE:
+ case OVS_ACTION_ATTR_SET:
+ case OVS_ACTION_ATTR_PUSH_VLAN:
+ case OVS_ACTION_ATTR_POP_VLAN:
+ case OVS_ACTION_ATTR_SAMPLE:
+ case OVS_ACTION_ATTR_RECIRC:
+ case OVS_ACTION_ATTR_HASH:
+ case OVS_ACTION_ATTR_PUSH_MPLS:
+ case OVS_ACTION_ATTR_POP_MPLS:
+ case OVS_ACTION_ATTR_SET_MASKED:
+ case OVS_ACTION_ATTR_CT:
+ case OVS_ACTION_ATTR_TRUNC:
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ case OVS_ACTION_ATTR_POP_ETH:
+ case OVS_ACTION_ATTR_CT_CLEAR:
+ case OVS_ACTION_ATTR_PUSH_NSH:
+ case OVS_ACTION_ATTR_POP_NSH:
+ case OVS_ACTION_ATTR_METER:
+ case OVS_ACTION_ATTR_CLONE:
+ case OVS_ACTION_ATTR_CHECK_PKT_LEN:
+ case OVS_ACTION_ATTR_ADD_MPLS:
+ case OVS_ACTION_ATTR_DEC_TTL:
+ case OVS_ACTION_ATTR_DROP:
+ case OVS_ACTION_ATTR_PSAMPLE:
+ case OVS_ACTION_ATTR_TUNNEL_POP:
+ case OVS_ACTION_ATTR_LB_OUTPUT:
+ case __OVS_ACTION_ATTR_MAX:
+ default:
return false;
}
}
@@ -664,8 +739,10 @@ dummy_offload_hw_process_pkt(const struct dpif_offload
*offload_,
NL_ATTR_FOR_EACH (nla, left, flow->actions, flow->actions_len) {
bool last_action = (left <= NLA_ALIGN(nla->nla_len));
+ enum ovs_action_attr action = nl_attr_type(nla);
- if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) {
+ switch (action) {
+ case OVS_ACTION_ATTR_OUTPUT: {
odp_port_t odp_port = nl_attr_get_odp_port(nla);
struct dummy_offload_port *port;
struct dp_packet_batch batch;
@@ -684,6 +761,55 @@ dummy_offload_hw_process_pkt(const struct dpif_offload
*offload_,
* for now we assume hash steering based on the number of queues
* configured for the dummy-netdev. */
netdev_send(port->pm_port.netdev, hash % n_txq, &batch, false);
+ break;
+ }
+ case OVS_ACTION_ATTR_TUNNEL_PUSH: {
+ const struct ovs_action_push_tnl *data = nl_attr_get(nla);
+ struct udp_header *udp;
+ struct flow ovs_flow;
+ ovs_be16 src_port;
+
+ src_port = dummy_offload_udp_tnl_get_src_port__(pkt);
+ netdev_tnl_push_udp_header(NULL, NULL, pkt, data);
+
+ flow_extract(pkt, &ovs_flow);
+ udp = dp_packet_l4(pkt);
+ ovs_assert(ovs_flow.nw_proto == IPPROTO_UDP && udp);
+
+ udp->udp_src = src_port;
+ break;
+ }
+
+ case OVS_ACTION_ATTR_UNSPEC:
+ case OVS_ACTION_ATTR_USERSPACE:
+ case OVS_ACTION_ATTR_SET:
+ case OVS_ACTION_ATTR_PUSH_VLAN:
+ case OVS_ACTION_ATTR_POP_VLAN:
+ case OVS_ACTION_ATTR_SAMPLE:
+ case OVS_ACTION_ATTR_RECIRC:
+ case OVS_ACTION_ATTR_HASH:
+ case OVS_ACTION_ATTR_PUSH_MPLS:
+ case OVS_ACTION_ATTR_POP_MPLS:
+ case OVS_ACTION_ATTR_SET_MASKED:
+ case OVS_ACTION_ATTR_CT:
+ case OVS_ACTION_ATTR_TRUNC:
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ case OVS_ACTION_ATTR_POP_ETH:
+ case OVS_ACTION_ATTR_CT_CLEAR:
+ case OVS_ACTION_ATTR_PUSH_NSH:
+ case OVS_ACTION_ATTR_POP_NSH:
+ case OVS_ACTION_ATTR_METER:
+ case OVS_ACTION_ATTR_CLONE:
+ case OVS_ACTION_ATTR_CHECK_PKT_LEN:
+ case OVS_ACTION_ATTR_ADD_MPLS:
+ case OVS_ACTION_ATTR_DEC_TTL:
+ case OVS_ACTION_ATTR_DROP:
+ case OVS_ACTION_ATTR_PSAMPLE:
+ case OVS_ACTION_ATTR_TUNNEL_POP:
+ case OVS_ACTION_ATTR_LB_OUTPUT:
+ case __OVS_ACTION_ATTR_MAX:
+ default:
+ OVS_NOT_REACHED();
}
}
@@ -1062,6 +1188,7 @@ dummy_pmd_thread_lifecycle(const struct dpif_offload
*dpif_offload,
.port_del = dummy_offload_port_del, \
.get_netdev = dummy_offload_get_netdev, \
.netdev_hw_post_process = dummy_offload_hw_post_process, \
+ .netdev_udp_tnl_get_src_port = dummy_offload_udp_tnl_get_src_port, \
.netdev_flow_put = dummy_flow_put, \
.netdev_flow_del = dummy_flow_del, \
.netdev_flow_stats = dummy_flow_stats, \
diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
index 259de2c299..e55d599519 100644
--- a/lib/dpif-offload-provider.h
+++ b/lib/dpif-offload-provider.h
@@ -279,6 +279,19 @@ struct dpif_offload_class {
unsigned pmd_id, struct dp_packet *,
void **flow_reference);
+ /* Allows the offload provider to override the default UDP tunnel source
+ * port selection. Called during tunnel encapsulation to determine the
+ * source port for UDP-based tunnels (VXLAN, Geneve, etc.).
+ *
+ * If implemented, should return true and set 'src_port' to the desired
+ * source port value. If not implemented or if default behavior is
+ * desired, should return false to use the standard source port
+ * calculation. */
+ bool (*netdev_udp_tnl_get_src_port)(const struct dpif_offload *,
+ const struct netdev *ingress_netdev,
+ const struct dp_packet *packet,
+ ovs_be16 *src_port);
+
/* Add or modify the specified flow directly in the offload datapath.
* The actual implementation may choose to handle the offload
* asynchronously by returning EINPROGRESS and invoking the supplied
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index cbf1f6c704..341decfdff 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -1465,6 +1465,25 @@ dpif_offload_netdev_hw_post_process(struct netdev
*netdev, unsigned pmd_id,
return rc;
}
+bool
+dpif_offload_netdev_udp_tnl_get_src_port(const struct netdev *ingress_netdev,
+ const struct dp_packet *packet,
+ ovs_be16 *src_port)
+{
+ const struct dpif_offload *offload;
+
+ offload = ovsrcu_get(const struct dpif_offload *,
+ &ingress_netdev->dpif_offload);
+
+ if (OVS_UNLIKELY(!offload)
+ || !offload->class->netdev_udp_tnl_get_src_port) {
+ return false;
+ }
+
+ return offload->class->netdev_udp_tnl_get_src_port(offload, ingress_netdev,
+ packet, src_port);
+}
+
void
dpif_offload_datapath_register_flow_unreference_cb(
struct dpif *dpif, dpif_offload_flow_unreference_cb *cb)
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index 0f66d8cd8e..6671b3147a 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -114,8 +114,10 @@ bool dpif_offload_netdev_same_offload(const struct netdev
*,
int dpif_offload_netdev_hw_post_process(struct netdev *, unsigned pmd_id,
struct dp_packet *,
void **flow_reference);
+bool dpif_offload_netdev_udp_tnl_get_src_port(const struct netdev *,
+ const struct dp_packet *,
+ ovs_be16 *src_port);
-
/* Callback invoked when a hardware flow offload operation (put/del)
completes.
* This callback is used for asynchronous flow offload operations. When the
* offload provider cannot complete an operation synchronously (returns
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 008b452b8a..f27b8b6926 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -36,6 +36,7 @@
#include "coverage.h"
#include "csum.h"
#include "dp-packet.h"
+#include "dpif-offload.h"
#include "netdev.h"
#include "netdev-vport.h"
#include "netdev-vport-private.h"
@@ -301,6 +302,7 @@ tnl_ol_pop(struct dp_packet *packet, int off)
void
netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
{
@@ -312,7 +314,10 @@ netdev_tnl_push_udp_header(const struct netdev *netdev
OVS_UNUSED,
/* We may need to re-calculate the hash and this has to be done before
* modifying the packet. */
- udp_src = netdev_tnl_get_src_port(packet);
+ if (!ingress_netdev || !dpif_offload_netdev_udp_tnl_get_src_port(
+ ingress_netdev, packet, &udp_src)) {
+ udp_src = netdev_tnl_get_src_port(packet);
+ }
tnl_ol_push(packet, data);
udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len,
@@ -532,6 +537,7 @@ err:
void
netdev_gre_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev OVS_UNUSED,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
{
@@ -695,6 +701,7 @@ err:
void
netdev_erspan_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev OVS_UNUSED,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
{
@@ -868,6 +875,7 @@ err:
void
netdev_gtpu_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev OVS_UNUSED,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
{
@@ -1001,6 +1009,7 @@ netdev_srv6_build_header(const struct netdev *netdev,
void
netdev_srv6_push_header(const struct netdev *netdev OVS_UNUSED,
+ const struct netdev *ingress_netdev OVS_UNUSED,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
{
diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h
index 47d6b6bbcf..ec1531d550 100644
--- a/lib/netdev-native-tnl.h
+++ b/lib/netdev-native-tnl.h
@@ -35,6 +35,7 @@ netdev_gre_build_header(const struct netdev *netdev,
void
netdev_gre_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
struct dp_packet *
@@ -47,6 +48,7 @@ netdev_erspan_build_header(const struct netdev *netdev,
void
netdev_erspan_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
struct dp_packet *
@@ -57,6 +59,7 @@ netdev_gtpu_pop_header(struct dp_packet *packet);
void
netdev_gtpu_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
@@ -68,6 +71,7 @@ netdev_gtpu_build_header(const struct netdev *netdev,
struct dp_packet *netdev_srv6_pop_header(struct dp_packet *);
void netdev_srv6_push_header(const struct netdev *,
+ const struct netdev *ingress_netdev,
struct dp_packet *,
const struct ovs_action_push_tnl *);
@@ -77,6 +81,7 @@ int netdev_srv6_build_header(const struct netdev *,
void
netdev_tnl_push_udp_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
int
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 136d8188c2..9aedb101fb 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -336,8 +336,13 @@ struct netdev_class {
/* build_header() can not build entire header for all packets for given
* flow. Push header is called for packet to build header specific to
* a packet on actual transmit. It uses partial header build by
- * build_header() which is passed as data. */
- void (*push_header)(const struct netdev *,
+ * build_header() which is passed as data.
+ *
+ * The 'ingress_netdev' points to the original ingress netdev for the
+ * 'packet'. This variable is valid only if hardware offload is enabled;
+ * otherwise, it will be NULL. */
+ void (*push_header)(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
diff --git a/lib/netdev.c b/lib/netdev.c
index daa4287362..2f08468c21 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1003,6 +1003,7 @@ int netdev_build_header(const struct netdev *netdev,
* that netdev_has_tunnel_push_pop() returns true. */
int
netdev_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet_batch *batch,
const struct ovs_action_push_tnl *data)
{
@@ -1038,7 +1039,8 @@ netdev_push_header(const struct netdev *netdev,
}
dp_packet_ol_send_prepare(packet, 0);
}
- netdev->netdev_class->push_header(netdev, packet, data);
+ netdev->netdev_class->push_header(netdev, ingress_netdev, packet,
+ data);
pkt_metadata_init(&packet->md, data->out_port);
dp_packet_batch_refill(batch, packet, i);
diff --git a/lib/netdev.h b/lib/netdev.h
index 40f1621eca..8aab8bc062 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -259,6 +259,7 @@ int netdev_build_header(const struct netdev *, struct
ovs_action_push_tnl *data,
const struct netdev_tnl_build_header_params *params);
int netdev_push_header(const struct netdev *netdev,
+ const struct netdev *ingress_netdev,
struct dp_packet_batch *,
const struct ovs_action_push_tnl *data);
void netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *);
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 0480730cab..5b6c961f90 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -77,6 +77,17 @@ strip_metadata () {
]
m4_divert_pop([PREPARE_TESTS])
+m4_define([CHECK_FWD_PACKET],
+ [m4_if([$3], [], [], [AT_CHECK([ovs-vsctl set interface $1
options:$3=true])])
+ AT_CHECK([ovs-appctl netdev-dummy/receive $1 $(cat $4)])
+ m4_if([$5], [none], [], [
+ AT_CHECK([awk 1 $5 > expout]) dnl Also normalizes the line endings.
+ AT_CHECK([ovs-pcap $2.pcap > $2.pcap.txt 2>&1])
+ AT_CHECK([tail -n 1 $2.pcap.txt], [0], [expout])
+ ])
+ m4_if([$3], [], [], [AT_CHECK([ovs-vsctl remove interface $1 options $3])])
+])
+
AT_SETUP([dpif-netdev - netdev-dummy/receive])
# Create br0 with interfaces p0
OVS_VSWITCHD_START([add-port br0 p1 -- set interface p1 type=dummy
ofport_request=1 -- ])
@@ -761,6 +772,85 @@ rx_offload_pipe_abort:1
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([dpif-netdev - full hw offload - tunnel entropy - dummy-pmd])
+OVS_VSWITCHD_START(
+ [add-br br1 -- set bridge br1 datapath-type=dummy -- \
+ add-port br1 p1 -- \
+ set Interface p1 type=dummy-pmd -- \
+ add-br br2 -- set bridge br2 datapath-type=dummy -- \
+ set bridge br2 other-config:hwaddr=aa:66:aa:66:00:00 -- \
+ add-port br2 p2 -- \
+ set Interface p2 type=dummy-pmd], [], [], [--dummy-numa 0])
+
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
+OVS_WAIT_UNTIL([grep "Flow HW offload is enabled" ovs-vswitchd.log])
+
+AT_CHECK([ovs-vsctl add-port br1 t1 \
+ -- set Interface t1 type=vxlan \
+ options:remote_ip=1.1.2.92 options:key=123 \
+ options:csum=false ofport_request=11], [0])
+AT_CHECK([ovs-ofctl add-flow br1
in_port=p1,actions=mod_nw_dst:192.168.1.1,output:11])
+
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br2 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl tnl/neigh/set br2 1.1.2.92 aa:66:aa:66:00:01], [0], [OK
+])
+AT_CHECK([ovs-appctl tnl/egress_port_range 57363 57363], [0], [OK
+])
+AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg \
+ dpif_offload_dummy:file:dbg netdev_dummy:file:dbg])
+
+AT_CHECK([ovs-vsctl set Interface p2 options:tx_pcap=p2.pcap])
+
+dnl ICMPv6.
+AT_DATA([ndp_frame], m4_join([],
+dnl p = Ether(src='04:bf:1b:d8:2d:2d', dst='33:33:ff:00:00:01')
+[3333ff00000104bf1bd82d2d86dd],
+dnl p /= IPv6(src='fe80::2', dst='ff02::1:ff00:1')
+[6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff000001],
+dnl p /= ICMPv6ND_NS(type=135, tgt='fe80::1')
+[87006e2600000000fe800000000000000000000000000001],
+dnl p /= ICMPv6NDOptSrcLLAddr(lladdr='8a:bf:7e:2f:05:84')
+[01018abf7e2f0584]
+))
+
+AT_DATA([ndp_expected], m4_join([],
+dnl p = Ether(src='aa:66:aa:66:00:00', dst='aa:66:aa:66:00:01')
+[aa66aa660001aa66aa6600000800],
+dnl p /= IP(src='1.1.2.88', dst='1.1.2.92', id=0, flags='DF')
+[4500007a00004000401133be010102580101025c],
+dnl p /= UDP(sport=43938, chksum=0)
+[aba212b500660000],
+dnl p /= VXLAN(vni=123, flags='Instance')
+[0800000000007b00],
+dnl p /= Ether(src='04:bf:1b:d8:2d:2d', dst='33:33:ff:00:00:01')
+[3333ff00000104bf1bd82d2d86dd],
+dnl p /= IPv6(src='fe80::2', dst='ff02::1:ff00:1')
+[6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff000001],
+dnl p /= ICMPv6ND_NS(type=135, tgt='fe80::1')
+[87006e2600000000fe800000000000000000000000000001],
+dnl p /= ICMPv6NDOptSrcLLAddr(lladdr='8a:bf:7e:2f:05:84')
+[01018abf7e2f0584]
+))
+
+# Sent two packets, second should be handled in hardware.
+CHECK_FWD_PACKET(p1, p2, , [ndp_frame], [ndp_expected])
+CHECK_FWD_PACKET(p1, p2, , [ndp_frame], [ndp_expected])
+
+# Check if we do not hit partial hw offload.
+AT_CHECK(
+ [ovs-appctl --format json dpif/offload/show \
+ | sed 's/.*"p1":{\([[^}]]*\)}.*/\1/; s/,/\n/g; s/"//g' \
+ | sed -n '/^rx_offload_/p' | sort], [0], [dnl
+rx_offload_full:1
+rx_offload_miss:1
+rx_offload_partial:0
+rx_offload_pipe_abort:0
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match])
OVS_VSWITCHD_START(
[add-port br0 p1 \
@@ -877,17 +967,6 @@ AT_CHECK([test `ovs-vsctl get Interface p2
statistics:tx_q0_packets` -gt 0 -a dn
OVS_VSWITCHD_STOP
AT_CLEANUP
-m4_define([CHECK_FWD_PACKET],
- [m4_if([$3], [], [], [AT_CHECK([ovs-vsctl set interface $1
options:$3=true])])
- AT_CHECK([ovs-appctl netdev-dummy/receive $1 $(cat $4)])
- m4_if([$5], [none], [], [
- AT_CHECK([awk 1 $5 > expout]) dnl Also normalizes the line endings.
- AT_CHECK([ovs-pcap $2.pcap > $2.pcap.txt 2>&1])
- AT_CHECK([tail -n 1 $2.pcap.txt], [0], [expout])
- ])
- m4_if([$3], [], [], [AT_CHECK([ovs-vsctl remove interface $1 options $3])])
-])
-
dnl CHECK_IP_CHECKSUMS rx_port tx_port good_pkt bad_pkt good_exp bad_exp
dnl
dnl Test combinations of Rx IP checksum flags for a good or bad packet
diff --git a/utilities/checkpatch_dict.txt b/utilities/checkpatch_dict.txt
index 0972cba603..35d2fd95bb 100644
--- a/utilities/checkpatch_dict.txt
+++ b/utilities/checkpatch_dict.txt
@@ -142,6 +142,7 @@ lldp
llvm
localnet
lockless
+lookups
loopback
malloc
mbps
--
2.52.0