@@ -43,6 +43,7 @@
#include "uuid.h"
#include "openvswitch/vlog.h"
#include "openvswitch/match.h"
+#include "odp-netlink-macros.h"
VLOG_DEFINE_THIS_MODULE(odp_util);
@@ -7361,12 +7362,51 @@ commit_odp_tunnel_action(const struct flow *flow, struct flow *base,
}
}
+struct offsetof_sizeof {
+ int offset;
+ int size;
+};
+
+/* Compare the keys similary to memcmp, but each field separately.
+ * The offsets and sizes of each field is provided by offsetof_sizeof_arr
+ * argument.
+ * For fields with the same value, zero out their mask part in order not to
+ * rewrite them as it's unnecessary */
+static bool
+keycmp_mask(const void *key0, const void *key1,
+ struct offsetof_sizeof *offsetof_sizeof_arr, void *mask)
+{
+ int field;
+ bool differ = false;
+
+ for (field = 0 ; ; field++) {
+ int size = offsetof_sizeof_arr[field].size;
+ int offset = offsetof_sizeof_arr[field].offset;
+ char *pkey0 = ((char *)key0) + offset;
+ char *pkey1 = ((char *)key1) + offset;
+ char *pmask = ((char *)mask) + offset;
+
+ if (size == 0) {
+ break;
+ }
+
+ if (memcmp(pkey0, pkey1, size) == 0) {
+ memset(pmask, 0, size);
+ } else {
+ differ = true;
+ }
+ }
+
+ return differ;
+}
+
static bool
commit(enum ovs_key_attr attr, bool use_masked_set,
const void *key, void *base, void *mask, size_t size,
+ struct offsetof_sizeof *offsetof_sizeof_arr,
struct ofpbuf *odp_actions)
{
- if (memcmp(key, base, size)) {
+ if (keycmp_mask(key, base, offsetof_sizeof_arr, mask)) {
bool fully_masked = odp_mask_is_exact(attr, mask, size);
if (use_masked_set && !fully_masked) {
@@ -7408,7 +7448,8 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
bool use_masked)
{
struct ovs_key_ethernet key, base, mask;
-
+ struct offsetof_sizeof ovs_key_ethernet_offsetof_sizeof_arr[] =
+ OVS_KEY_ETHERNET_OFFSETOF_SIZEOF_ARR;
if (flow->packet_type != htonl(PT_ETH)) {
return;
}
@@ -7418,7 +7459,8 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
get_ethernet_key(&wc->masks, &mask);
if (commit(OVS_KEY_ATTR_ETHERNET, use_masked,
- &key, &base, &mask, sizeof key, odp_actions)) {
+ &key, &base, &mask, sizeof key,
+ ovs_key_ethernet_offsetof_sizeof_arr, odp_actions)) {
put_ethernet_key(&base, base_flow);
put_ethernet_key(&mask, &wc->masks);
}
@@ -7544,6 +7586,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
bool use_masked)
{
struct ovs_key_ipv4 key, mask, base;
+ struct offsetof_sizeof ovs_key_ipv4_offsetof_sizeof_arr[] =
+ OVS_KEY_IPV4_OFFSETOF_SIZEOF_ARR;
/* Check that nw_proto and nw_frag remain unchanged. */
ovs_assert(flow->nw_proto == base_flow->nw_proto &&
@@ -7561,7 +7605,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
}
if (commit(OVS_KEY_ATTR_IPV4, use_masked, &key, &base, &mask, sizeof key,
- odp_actions)) {
+ ovs_key_ipv4_offsetof_sizeof_arr, odp_actions)) {
put_ipv4_key(&base, base_flow, false);
if (mask.ipv4_proto != 0) { /* Mask was changed by commit(). */
put_ipv4_key(&mask, &wc->masks, true);
@@ -7599,6 +7643,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
bool use_masked)
{
struct ovs_key_ipv6 key, mask, base;
+ struct offsetof_sizeof ovs_key_ipv6_offsetof_sizeof_arr[] =
+ OVS_KEY_IPV6_OFFSETOF_SIZEOF_ARR;
/* Check that nw_proto and nw_frag remain unchanged. */
ovs_assert(flow->nw_proto == base_flow->nw_proto &&
@@ -7617,7 +7663,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
}
if (commit(OVS_KEY_ATTR_IPV6, use_masked, &key, &base, &mask, sizeof key,
- odp_actions)) {
+ ovs_key_ipv6_offsetof_sizeof_arr, odp_actions)) {
put_ipv6_key(&base, base_flow, false);
if (mask.ipv6_proto != 0) { /* Mask was changed by commit(). */
put_ipv6_key(&mask, &wc->masks, true);
@@ -7653,13 +7699,15 @@ commit_set_arp_action(const struct flow *flow, struct flow *base_flow,
struct ofpbuf *odp_actions, struct flow_wildcards *wc)
{
struct ovs_key_arp key, mask, base;
+ struct offsetof_sizeof ovs_key_arp_offsetof_sizeof_arr[] =
+ OVS_KEY_ARP_OFFSETOF_SIZEOF_ARR;
get_arp_key(flow, &key);
get_arp_key(base_flow, &base);
get_arp_key(&wc->masks, &mask);
if (commit(OVS_KEY_ATTR_ARP, true, &key, &base, &mask, sizeof key,
- odp_actions)) {
+ ovs_key_arp_offsetof_sizeof_arr, odp_actions)) {
put_arp_key(&base, base_flow);
put_arp_key(&mask, &wc->masks);
return SLOW_ACTION;
@@ -7688,6 +7736,8 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
struct ofpbuf *odp_actions, struct flow_wildcards *wc)
{
struct ovs_key_icmp key, mask, base;
+ struct offsetof_sizeof ovs_key_icmp_offsetof_sizeof_arr[] =
+ OVS_KEY_ICMP_OFFSETOF_SIZEOF_ARR;
enum ovs_key_attr attr;
if (is_icmpv4(flow, NULL)) {
@@ -7702,7 +7752,8 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
get_icmp_key(base_flow, &base);
get_icmp_key(&wc->masks, &mask);
- if (commit(attr, false, &key, &base, &mask, sizeof key, odp_actions)) {
+ if (commit(attr, false, &key, &base, &mask, sizeof key,
+ ovs_key_icmp_offsetof_sizeof_arr, odp_actions)) {
put_icmp_key(&base, base_flow);
put_icmp_key(&mask, &wc->masks);
return SLOW_ACTION;
@@ -7752,13 +7803,15 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow,
struct flow_wildcards *wc, bool use_masked)
{
struct ovs_key_nd key, mask, base;
+ struct offsetof_sizeof ovs_key_nd_offsetof_sizeof_arr[] =
+ OVS_KEY_ND_OFFSETOF_SIZEOF_ARR;
get_nd_key(flow, &key);
get_nd_key(base_flow, &base);
get_nd_key(&wc->masks, &mask);
if (commit(OVS_KEY_ATTR_ND, use_masked, &key, &base, &mask, sizeof key,
- odp_actions)) {
+ ovs_key_nd_offsetof_sizeof_arr, odp_actions)) {
put_nd_key(&base, base_flow);
put_nd_key(&mask, &wc->masks);
return SLOW_ACTION;
@@ -7774,13 +7827,16 @@ commit_set_nd_extensions_action(const struct flow *flow,
struct flow_wildcards *wc, bool use_masked)
{
struct ovs_key_nd_extensions key, mask, base;
+ struct offsetof_sizeof ovs_key_nd_extensions_offsetof_sizeof_arr[] =
+ OVS_KEY_ND_EXTENSIONS_OFFSETOF_SIZEOF_ARR;
get_nd_extensions_key(flow, &key);
get_nd_extensions_key(base_flow, &base);
get_nd_extensions_key(&wc->masks, &mask);
- if (commit(OVS_KEY_ATTR_ND_EXTENSIONS, use_masked, &key,
- &base, &mask, sizeof key, odp_actions)) {
+ if (commit(OVS_KEY_ATTR_ND_EXTENSIONS, use_masked, &key, &base, &mask,
+ sizeof key, ovs_key_nd_extensions_offsetof_sizeof_arr,
+ odp_actions)) {
put_nd_extensions_key(&base, base_flow);
put_nd_extensions_key(&mask, &wc->masks);
return SLOW_ACTION;
@@ -7997,6 +8053,8 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
{
enum ovs_key_attr key_type;
union ovs_key_tp key, mask, base;
+ struct offsetof_sizeof ovs_key_tp_offsetof_sizeof_arr[] =
+ OVS_KEY_TCP_OFFSETOF_SIZEOF_ARR;
/* Check if 'flow' really has an L3 header. */
if (!flow->nw_proto) {
@@ -8022,7 +8080,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
get_tp_key(&wc->masks, &mask);
if (commit(key_type, use_masked, &key, &base, &mask, sizeof key,
- odp_actions)) {
+ ovs_key_tp_offsetof_sizeof_arr, odp_actions)) {
put_tp_key(&base, base_flow);
put_tp_key(&mask, &wc->masks);
}
@@ -8035,13 +8093,17 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
bool use_masked)
{
uint32_t key, mask, base;
+ struct offsetof_sizeof ovs_key_prio_offsetof_sizeof_arr[] = {
+ {0, sizeof(uint32_t)},
+ {0, 0}
+ };
key = flow->skb_priority;
base = base_flow->skb_priority;
mask = wc->masks.skb_priority;
if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask,
- sizeof key, odp_actions)) {
+ sizeof key, ovs_key_prio_offsetof_sizeof_arr, odp_actions)) {
base_flow->skb_priority = base;
wc->masks.skb_priority = mask;
}
@@ -8054,13 +8116,18 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow,
bool use_masked)
{
uint32_t key, mask, base;
+ struct offsetof_sizeof ovs_key_pkt_mark_offsetof_sizeof_arr[] = {
+ {0, sizeof(uint32_t)},
+ {0, 0}
+ };
key = flow->pkt_mark;
base = base_flow->pkt_mark;
mask = wc->masks.pkt_mark;
if (commit(OVS_KEY_ATTR_SKB_MARK, use_masked, &key, &base, &mask,
- sizeof key, odp_actions)) {
+ sizeof key, ovs_key_pkt_mark_offsetof_sizeof_arr,
+ odp_actions)) {
base_flow->pkt_mark = base;
wc->masks.pkt_mark = mask;
}
@@ -182,7 +182,7 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br1 in_port=1,ip,actions=dec_ttl,push
dnl MPLS push+pop
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=10.1.1.22,dst=10.0.0.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=53295,dst=8080)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: set(ipv4(ttl=63)),push_mpls(label=0,tc=0,ttl=63,bos=1,eth_type=0x8847),3,pop_mpls(eth_type=0x800),set(ipv4(tos=0/0xfc,ttl=64)),1,1
+ [Datapath actions: set(ipv4(ttl=63)),push_mpls(label=0,tc=0,ttl=63,bos=1,eth_type=0x8847),3,pop_mpls(eth_type=0x800),set(ipv4(ttl=64)),1,1
])
OVS_VSWITCHD_STOP
@@ -4346,7 +4346,7 @@ do
elif test $type = later; then
echo "Datapath actions: $exp_output" >> expout
else
- echo "Datapath actions: set(tcp(src=80,dst=80)),$exp_output" >> expout
+ echo "Datapath actions: set(tcp(src=80)),$exp_output" >> expout
fi
AT_CHECK([grep 'IP fragments' stdout; tail -1 stdout], [0], [expout])
done
@@ -7252,7 +7252,7 @@ AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(src=10.10.10.2,dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(src=10.10.10.2,dst=10.10.10.1)),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])
dnl Test flow xlate openflow clone action without using datapath clone action.
@@ -7261,14 +7261,14 @@ AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone false], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(src=10.10.10.2,dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(src=10.10.10.2,dst=10.10.10.1)),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])
AT_CHECK([ovs-appctl dpif/set-dp-features br0 sample_nesting 2], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(src=10.10.10.2,dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(src=10.10.10.2,dst=10.10.10.1)),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(dst=10.10.10.1)),4
])
dnl Mixing reversible and irreversible open flow clone actions. Datapath clone action
@@ -7286,7 +7286,7 @@ AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(ipv4(src=10.10.10.2,dst=10.10.10.1)),clone(ct(commit),3),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),clone(ct(commit),3),4
])
AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone false], [0], [ignore])
@@ -7294,14 +7294,14 @@ AT_CHECK([ovs-appctl dpif/set-dp-features br0 clone false], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(ipv4(src=10.10.10.2,dst=10.10.10.1)),sample(sample=100.0%,actions(ct(commit),3)),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),sample(sample=100.0%,actions(ct(commit),3)),4
])
AT_CHECK([ovs-appctl dpif/set-dp-features br0 sample_nesting 2], [0], [ignore])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(ipv4(src=10.10.10.2,dst=10.10.10.1)),4
+Datapath actions: set(ipv4(dst=192.168.4.4)),2,set(ipv4(dst=10.10.10.1)),4
])
AT_CHECK([grep "Failed to compose clone action" stdout], [0], [ignore])