+ if (mask && ovs_scan(s, "vlan(vid=%i/%i,pcp=%i/%i)%n",
+ &vid, &vid_mask, &pcp, &pcp_mask, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_VLAN,
+ htons((vid << VLAN_VID_SHIFT) |
+ (pcp << VLAN_PCP_SHIFT) |
+ VLAN_CFI));
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_VLAN,
+ htons((vid_mask << VLAN_VID_SHIFT) |
+ (pcp_mask << VLAN_PCP_SHIFT) |
+ (1 << VLAN_CFI_SHIFT)));
+ return n;
+ } else if (ovs_scan(s, "vlan(vid=%i,pcp=%i)%n", &vid, &pcp, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_VLAN,
+ htons((vid << VLAN_VID_SHIFT) |
+ (pcp << VLAN_PCP_SHIFT) |
+ VLAN_CFI));
+ if (mask) {
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_VLAN, OVS_BE16_MAX);
+ }
+ return n;
+ } else if (mask
+ && ovs_scan(s, "vlan(vid=%i/%i,pcp=%i/%i,cfi=%i/%i)%n",
+ &vid, &vid_mask, &pcp, &pcp_mask,
+ &cfi, &cfi_mask, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_VLAN,
+ htons((vid << VLAN_VID_SHIFT) |
+ (pcp << VLAN_PCP_SHIFT) |
+ (cfi ? VLAN_CFI : 0)));
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_VLAN,
+ htons((vid_mask << VLAN_VID_SHIFT) |
+ (pcp_mask << VLAN_PCP_SHIFT) |
+ (cfi_mask << VLAN_CFI_SHIFT)));
+ return n;
+ } else if (ovs_scan(s, "vlan(vid=%i,pcp=%i,cfi=%i)%n",
+ &vid, &pcp, &cfi, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_VLAN,
+ htons((vid << VLAN_VID_SHIFT) |
+ (pcp << VLAN_PCP_SHIFT) |
+ (cfi ? VLAN_CFI : 0)));
+ if (mask) {
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_VLAN, OVS_BE16_MAX);
+ }
+ return n;
+ }
+ }
+
+ {
+ int eth_type;
+ int eth_type_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "eth_type(%i/%i)%n",
+ ð_type, ð_type_mask, &n)) {
+ if (eth_type != 0) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type));
+ }
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type_mask));
+ return n;
+ } else if (ovs_scan(s, "eth_type(%i)%n", ð_type, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type));
+ if (mask) {
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_ETHERTYPE, OVS_BE16_MAX);
+ }
+ return n;
+ }
+ }
+
+ {
+ int label, tc, ttl, bos;
+ int label_mask, tc_mask, ttl_mask, bos_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "mpls(label=%i/%i,tc=%i/%i,"
+ "ttl=%i/%i,bos=%i/%i)%n",
+ &label, &label_mask, &tc, &tc_mask,
+ &ttl, &ttl_mask, &bos, &bos_mask, &n)) {
+ struct ovs_key_mpls *mpls, *mpls_mask;
+
+ mpls = nl_msg_put_unspec_uninit(key, OVS_KEY_ATTR_MPLS,
+ sizeof *mpls);
+ mpls->mpls_lse = mpls_lse_from_components(label, tc, ttl, bos);
+
+ mpls_mask = nl_msg_put_unspec_uninit(mask, OVS_KEY_ATTR_MPLS,
+ sizeof *mpls_mask);
+ mpls_mask->mpls_lse = mpls_lse_from_components(
+ label_mask, tc_mask, ttl_mask, bos_mask);
+ return n;
+ } else if (ovs_scan(s, "mpls(label=%i,tc=%i,ttl=%i,bos=%i)%n",
+ &label, &tc, &ttl, &bos, &n)) {
+ struct ovs_key_mpls *mpls;
+
+ mpls = nl_msg_put_unspec_uninit(key, OVS_KEY_ATTR_MPLS,
+ sizeof *mpls);
+ mpls->mpls_lse = mpls_lse_from_components(label, tc, ttl, bos);
+ if (mask) {
+ mpls = nl_msg_put_unspec_uninit(mask, OVS_KEY_ATTR_MPLS,
+ sizeof *mpls);
+ mpls->mpls_lse = OVS_BE32_MAX;
+ }
+ return n;
+ }
+ }
+
+
+ {
+ struct ovs_key_ipv4 ipv4_key;
+ struct ovs_key_ipv4 ipv4_mask;
+
+ char frag[8];
+ enum ovs_frag_type ipv4_frag;
+ int n = -1;
+
+ if (mask
+ && ovs_scan(s, "ipv4(src="IP_SCAN_FMT"/"IP_SCAN_FMT","
+ "dst="IP_SCAN_FMT"/"IP_SCAN_FMT","
+ "proto=%"SCNi8"/%"SCNi8","
+ "tos=%"SCNi8"/%"SCNi8","
+ "ttl=%"SCNi8"/%"SCNi8","
+ "frag=%7[a-z]/%"SCNi8")%n",
+ IP_SCAN_ARGS(&ipv4_key.ipv4_src),
+ IP_SCAN_ARGS(&ipv4_mask.ipv4_src),
+ IP_SCAN_ARGS(&ipv4_key.ipv4_dst),
+ IP_SCAN_ARGS(&ipv4_mask.ipv4_dst),
+ &ipv4_key.ipv4_proto, &ipv4_mask.ipv4_proto,
+ &ipv4_key.ipv4_tos, &ipv4_mask.ipv4_tos,
+ &ipv4_key.ipv4_ttl, &ipv4_mask.ipv4_ttl,
+ frag, &ipv4_mask.ipv4_frag, &n)
+ && ovs_frag_type_from_string(frag, &ipv4_frag)) {
+ ipv4_key.ipv4_frag = ipv4_frag;
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV4,
+ &ipv4_key, sizeof ipv4_key);
+
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_IPV4,
+ &ipv4_mask, sizeof ipv4_mask);
+ return n;
+ } else if (ovs_scan(s, "ipv4(src="IP_SCAN_FMT",dst="IP_SCAN_FMT","
+ "proto=%"SCNi8",tos=%"SCNi8",ttl=%"SCNi8","
+ "frag=%7[a-z])%n",
+ IP_SCAN_ARGS(&ipv4_key.ipv4_src),
+ IP_SCAN_ARGS(&ipv4_key.ipv4_dst),
+ &ipv4_key.ipv4_proto,
+ &ipv4_key.ipv4_tos,
+ &ipv4_key.ipv4_ttl,
+ frag, &n) > 0
+ && ovs_frag_type_from_string(frag, &ipv4_frag)) {
+ ipv4_key.ipv4_frag = ipv4_frag;
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV4,
+ &ipv4_key, sizeof ipv4_key);
+
+ if (mask) {
+ memset(&ipv4_key, 0xff, sizeof ipv4_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_IPV4,
+ &ipv4_key, sizeof ipv4_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ char ipv6_src_s[IPV6_SCAN_LEN + 1];
+ char ipv6_src_mask_s[IPV6_SCAN_LEN + 1];
+ char ipv6_dst_s[IPV6_SCAN_LEN + 1];
+ char ipv6_dst_mask_s[IPV6_SCAN_LEN + 1];
+ int ipv6_label, ipv6_label_mask;
+ int ipv6_proto, ipv6_proto_mask;
+ int ipv6_tclass, ipv6_tclass_mask;
+ int ipv6_hlimit, ipv6_hlimit_mask;
+ char frag[8];
+ enum ovs_frag_type ipv6_frag;
+ int ipv6_frag_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "ipv6(src="IPV6_SCAN_FMT"/"IPV6_SCAN_FMT",dst="
+ IPV6_SCAN_FMT"/"IPV6_SCAN_FMT","
+ "label=%i/%i,proto=%i/%i,tclass=%i/%i,"
+ "hlimit=%i/%i,frag=%7[a-z]/%i)%n",
+ ipv6_src_s, ipv6_src_mask_s,
+ ipv6_dst_s, ipv6_dst_mask_s,
+ &ipv6_label, &ipv6_label_mask, &ipv6_proto,
+ &ipv6_proto_mask, &ipv6_tclass, &ipv6_tclass_mask,
+ &ipv6_hlimit, &ipv6_hlimit_mask, frag,
+ &ipv6_frag_mask, &n)
+ && ovs_frag_type_from_string(frag, &ipv6_frag)) {
+ struct ovs_key_ipv6 ipv6_key;
+ struct ovs_key_ipv6 ipv6_mask;
+
+ if (inet_pton(AF_INET6, ipv6_src_s, &ipv6_key.ipv6_src) != 1 ||
+ inet_pton(AF_INET6, ipv6_dst_s, &ipv6_key.ipv6_dst) != 1 ||
+ inet_pton(AF_INET6, ipv6_src_mask_s, &ipv6_mask.ipv6_src) != 1 ||
+ inet_pton(AF_INET6, ipv6_dst_mask_s, &ipv6_mask.ipv6_dst) != 1) {
+ return -EINVAL;
+ }
+
+ ipv6_key.ipv6_label = htonl(ipv6_label);
+ ipv6_key.ipv6_proto = ipv6_proto;
+ ipv6_key.ipv6_tclass = ipv6_tclass;
+ ipv6_key.ipv6_hlimit = ipv6_hlimit;
+ ipv6_key.ipv6_frag = ipv6_frag;
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV6,
+ &ipv6_key, sizeof ipv6_key);
+
+ ipv6_mask.ipv6_label = htonl(ipv6_label_mask);
+ ipv6_mask.ipv6_proto = ipv6_proto_mask;
+ ipv6_mask.ipv6_tclass = ipv6_tclass_mask;
+ ipv6_mask.ipv6_hlimit = ipv6_hlimit_mask;
+ ipv6_mask.ipv6_frag = ipv6_frag_mask;
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_IPV6,
+ &ipv6_mask, sizeof ipv6_mask);
+ return n;
+ } else if (ovs_scan(s, "ipv6(src="IPV6_SCAN_FMT",dst="IPV6_SCAN_FMT","
+ "label=%i,proto=%i,tclass=%i,hlimit=%i,"
+ "frag=%7[a-z])%n",
+ ipv6_src_s, ipv6_dst_s, &ipv6_label,
+ &ipv6_proto, &ipv6_tclass, &ipv6_hlimit, frag, &n)
+ && ovs_frag_type_from_string(frag, &ipv6_frag)) {
+ struct ovs_key_ipv6 ipv6_key;
+
+ if (inet_pton(AF_INET6, ipv6_src_s, &ipv6_key.ipv6_src) != 1 ||
+ inet_pton(AF_INET6, ipv6_dst_s, &ipv6_key.ipv6_dst) != 1) {
+ return -EINVAL;
+ }
+ ipv6_key.ipv6_label = htonl(ipv6_label);
+ ipv6_key.ipv6_proto = ipv6_proto;
+ ipv6_key.ipv6_tclass = ipv6_tclass;
+ ipv6_key.ipv6_hlimit = ipv6_hlimit;
+ ipv6_key.ipv6_frag = ipv6_frag;
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV6,
+ &ipv6_key, sizeof ipv6_key);
+
+ if (mask) {
+ memset(&ipv6_key, 0xff, sizeof ipv6_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_IPV6,
+ &ipv6_key, sizeof ipv6_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ int tcp_src;
+ int tcp_dst;
+ int tcp_src_mask;
+ int tcp_dst_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "tcp(src=%i/%i,dst=%i/%i)%n",
+ &tcp_src, &tcp_src_mask, &tcp_dst,
+ &tcp_dst_mask, &n)) {
+ struct ovs_key_tcp tcp_key;
+ struct ovs_key_tcp tcp_mask;
+
+ tcp_key.tcp_src = htons(tcp_src);
+ tcp_key.tcp_dst = htons(tcp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_TCP, &tcp_key, sizeof tcp_key);
+
+ tcp_mask.tcp_src = htons(tcp_src_mask);
+ tcp_mask.tcp_dst = htons(tcp_dst_mask);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_TCP,
+ &tcp_mask, sizeof tcp_mask);
+ return n;
+ } else if (ovs_scan(s, "tcp(src=%i,dst=%i)%n",
+ &tcp_src, &tcp_dst, &n)) {
+ struct ovs_key_tcp tcp_key;
+
+ tcp_key.tcp_src = htons(tcp_src);
+ tcp_key.tcp_dst = htons(tcp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_TCP, &tcp_key, sizeof tcp_key);
+
+ if (mask) {
+ memset(&tcp_key, 0xff, sizeof tcp_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_TCP,
+ &tcp_key, sizeof tcp_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ uint16_t tcp_flags, tcp_flags_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "tcp_flags(%"SCNi16"/%"SCNi16")%n",
+ &tcp_flags, &tcp_flags_mask, &n) > 0 && n > 0) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags));
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags_mask));
+ return n;
+ } else if (ovs_scan(s, "tcp_flags(%"SCNi16")%n", &tcp_flags, &n)) {
+ nl_msg_put_be16(key, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags));
+ if (mask) {
+ nl_msg_put_be16(mask, OVS_KEY_ATTR_TCP_FLAGS,
+ htons(UINT16_MAX));
+ }
+ return n;
+ }
+ }
+
+ {
+ int udp_src;
+ int udp_dst;
+ int udp_src_mask;
+ int udp_dst_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "udp(src=%i/%i,dst=%i/%i)%n",
+ &udp_src, &udp_src_mask,
+ &udp_dst, &udp_dst_mask, &n)) {
+ struct ovs_key_udp udp_key;
+ struct ovs_key_udp udp_mask;
+
+ udp_key.udp_src = htons(udp_src);
+ udp_key.udp_dst = htons(udp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_UDP, &udp_key, sizeof udp_key);
+
+ udp_mask.udp_src = htons(udp_src_mask);
+ udp_mask.udp_dst = htons(udp_dst_mask);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_UDP,
+ &udp_mask, sizeof udp_mask);
+ return n;
+ }
+ if (ovs_scan(s, "udp(src=%i,dst=%i)%n", &udp_src, &udp_dst, &n)) {
+ struct ovs_key_udp udp_key;
+
+ udp_key.udp_src = htons(udp_src);
+ udp_key.udp_dst = htons(udp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_UDP, &udp_key, sizeof udp_key);
+
+ if (mask) {
+ memset(&udp_key, 0xff, sizeof udp_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_UDP, &udp_key, sizeof udp_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ int sctp_src;
+ int sctp_dst;
+ int sctp_src_mask;
+ int sctp_dst_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "sctp(src=%i/%i,dst=%i/%i)%n",
+ &sctp_src, &sctp_src_mask,
+ &sctp_dst, &sctp_dst_mask, &n)) {
+ struct ovs_key_sctp sctp_key;
+ struct ovs_key_sctp sctp_mask;
+
+ sctp_key.sctp_src = htons(sctp_src);
+ sctp_key.sctp_dst = htons(sctp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_SCTP, &sctp_key, sizeof sctp_key);
+
+ sctp_mask.sctp_src = htons(sctp_src_mask);
+ sctp_mask.sctp_dst = htons(sctp_dst_mask);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_SCTP,
+ &sctp_mask, sizeof sctp_mask);
+ return n;
+ }
+ if (ovs_scan(s, "sctp(src=%i,dst=%i)%n", &sctp_src, &sctp_dst, &n)) {
+ struct ovs_key_sctp sctp_key;
+
+ sctp_key.sctp_src = htons(sctp_src);
+ sctp_key.sctp_dst = htons(sctp_dst);
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_SCTP, &sctp_key, sizeof sctp_key);
+
+ if (mask) {
+ memset(&sctp_key, 0xff, sizeof sctp_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_SCTP, &sctp_key, sizeof sctp_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ struct ovs_key_icmp icmp_key;
+ struct ovs_key_icmp icmp_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "icmp(type=%"SCNi8"/%"SCNi8","
+ "code=%"SCNi8"/%"SCNi8")%n",
+ &icmp_key.icmp_type, &icmp_mask.icmp_type,
+ &icmp_key.icmp_code, &icmp_mask.icmp_code, &n)) {
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMP,
+ &icmp_key, sizeof icmp_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_ICMP,
+ &icmp_mask, sizeof icmp_mask);
+ return n;
+ } else if (ovs_scan(s, "icmp(type=%"SCNi8",code=%"SCNi8")%n",
+ &icmp_key.icmp_type, &icmp_key.icmp_code, &n)) {
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMP,
+ &icmp_key, sizeof icmp_key);
+ if (mask) {
+ memset(&icmp_key, 0xff, sizeof icmp_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_ICMP, &icmp_key,
+ sizeof icmp_key);
+ }
+ return n;
+ }
+ }
+
+ {
+ struct ovs_key_icmpv6 icmpv6_key;
+ struct ovs_key_icmpv6 icmpv6_mask;
+ int n = -1;
+
+ if (mask && ovs_scan(s, "icmpv6(type=%"SCNi8"/%"SCNi8","
+ "code=%"SCNi8"/%"SCNi8")%n",
+ &icmpv6_key.icmpv6_type, &icmpv6_mask.icmpv6_type,
+ &icmpv6_key.icmpv6_code, &icmpv6_mask.icmpv6_code,
+ &n)) {
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMPV6,
+ &icmpv6_key, sizeof icmpv6_key);
+ nl_msg_put_unspec(mask, OVS_KEY_ATTR_ICMPV6, &icmpv6_mask,
+ sizeof icmpv6_mask);
+ return n;
+ } else if (ovs_scan(s, "icmpv6(type=%"SCNi8",code=%"SCNi8")%n",
+ &icmpv6_key.icmpv6_type, &icmpv6_key.icmpv6_code,
+ &n)) {
+ nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMPV6,