+ for (i = 0; i < ARRAY_SIZE(dst->be16); i++) {
+ dst->be16[i] = src.be16[i] | (dst->be16[i] & ~mask.be16[i]);
+ }
+}
+
+static void
+odp_eth_set_addrs(struct dp_packet *packet, const struct ovs_key_ethernet *key,
+ const struct ovs_key_ethernet *mask)
+{
+ struct eth_header *eh = dp_packet_l2(packet);
+
+ if (eh) {
+ if (!mask) {
+ eh->eth_src = key->eth_src;
+ eh->eth_dst = key->eth_dst;
+ } else {
+ ether_addr_copy_masked(&eh->eth_src, key->eth_src, mask->eth_src);
+ ether_addr_copy_masked(&eh->eth_dst, key->eth_dst, mask->eth_dst);
+ }
+ }
+}
+
+static void
+odp_set_ipv4(struct dp_packet *packet, const struct ovs_key_ipv4 *key,
+ const struct ovs_key_ipv4 *mask)
+{
+ struct ip_header *nh = dp_packet_l3(packet);
+
+ packet_set_ipv4(
+ packet,
+ key->ipv4_src | (get_16aligned_be32(&nh->ip_src) & ~mask->ipv4_src),
+ key->ipv4_dst | (get_16aligned_be32(&nh->ip_dst) & ~mask->ipv4_dst),
+ key->ipv4_tos | (nh->ip_tos & ~mask->ipv4_tos),
+ key->ipv4_ttl | (nh->ip_ttl & ~mask->ipv4_ttl));
+}
+
+static const ovs_be32 *
+mask_ipv6_addr(const ovs_16aligned_be32 *old, const ovs_be32 *addr,
+ const ovs_be32 *mask, ovs_be32 *masked)
+{
+ for (int i = 0; i < 4; i++) {
+ masked[i] = addr[i] | (get_16aligned_be32(&old[i]) & ~mask[i]);
+ }
+
+ return masked;
+}
+
+static void
+odp_set_ipv6(struct dp_packet *packet, const struct ovs_key_ipv6 *key,
+ const struct ovs_key_ipv6 *mask)
+{
+ struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
+ ovs_be32 sbuf[4], dbuf[4];
+ uint8_t old_tc = ntohl(get_16aligned_be32(&nh->ip6_flow)) >> 20;
+ ovs_be32 old_fl = get_16aligned_be32(&nh->ip6_flow) & htonl(0xfffff);
+
+ packet_set_ipv6(
+ packet,
+ key->ipv6_proto,
+ mask_ipv6_addr(nh->ip6_src.be32, key->ipv6_src, mask->ipv6_src, sbuf),
+ mask_ipv6_addr(nh->ip6_dst.be32, key->ipv6_dst, mask->ipv6_dst, dbuf),
+ key->ipv6_tclass | (old_tc & ~mask->ipv6_tclass),
+ key->ipv6_label | (old_fl & ~mask->ipv6_label),
+ key->ipv6_hlimit | (nh->ip6_hlim & ~mask->ipv6_hlimit));
+}
+
+static void
+odp_set_tcp(struct dp_packet *packet, const struct ovs_key_tcp *key,
+ const struct ovs_key_tcp *mask)
+{
+ struct tcp_header *th = dp_packet_l4(packet);
+
+ if (OVS_LIKELY(th && dp_packet_get_tcp_payload(packet))) {
+ packet_set_tcp_port(packet,
+ key->tcp_src | (th->tcp_src & ~mask->tcp_src),
+ key->tcp_dst | (th->tcp_dst & ~mask->tcp_dst));
+ }
+}
+
+static void
+odp_set_udp(struct dp_packet *packet, const struct ovs_key_udp *key,
+ const struct ovs_key_udp *mask)
+{
+ struct udp_header *uh = dp_packet_l4(packet);
+
+ if (OVS_LIKELY(uh && dp_packet_get_udp_payload(packet))) {
+ packet_set_udp_port(packet,
+ key->udp_src | (uh->udp_src & ~mask->udp_src),
+ key->udp_dst | (uh->udp_dst & ~mask->udp_dst));
+ }
+}
+
+static void
+odp_set_sctp(struct dp_packet *packet, const struct ovs_key_sctp *key,
+ const struct ovs_key_sctp *mask)
+{
+ struct sctp_header *sh = dp_packet_l4(packet);
+
+ if (OVS_LIKELY(sh && dp_packet_get_sctp_payload(packet))) {
+ packet_set_sctp_port(packet,
+ key->sctp_src | (sh->sctp_src & ~mask->sctp_src),
+ key->sctp_dst | (sh->sctp_dst & ~mask->sctp_dst));
+ }