* This state machine accepts the following forms, with [] for optional
* elements and | for alternatives:
*
- * [tun_id] in_port ethernet [8021q] [ethertype \
+ * [tun_id] [in_port] ethernet [8021q] [ethertype \
* [IPv4 [TCP|UDP|ICMP] | IPv6 [TCP|UDP|ICMPv6 [ND]] | ARP]]
*/
int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
int key_len;
memset(swkey, 0, sizeof(*swkey));
+ swkey->eth.in_port = USHRT_MAX;
swkey->eth.type = htons(ETH_P_802_2);
key_len = SW_FLOW_KEY_OFFSET(eth);
swkey->eth.in_port = nla_get_u32(nla);
break;
+ case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_ETHERNET):
+ case TRANSITION(OVS_KEY_ATTR_TUN_ID, OVS_KEY_ATTR_ETHERNET):
case TRANSITION(OVS_KEY_ATTR_IN_PORT, OVS_KEY_ATTR_ETHERNET):
eth_key = nla_data(nla);
memcpy(swkey->eth.src, eth_key->eth_src, ETH_ALEN);
u16 prev_type;
int rem;
+ *in_port = USHRT_MAX;
*tun_id = 0;
prev_type = OVS_KEY_ATTR_UNSPEC;
break;
default:
- goto done;
+ return 0;
}
prev_type = type;
}
if (rem)
return -EINVAL;
-
-done:
- if (prev_type == OVS_KEY_ATTR_UNSPEC ||
- prev_type == OVS_KEY_ATTR_TUN_ID)
- return -EINVAL;
return 0;
}
if (swkey->eth.tun_id != cpu_to_be64(0))
NLA_PUT_BE64(skb, OVS_KEY_ATTR_TUN_ID, swkey->eth.tun_id);
- NLA_PUT_U32(skb, OVS_KEY_ATTR_IN_PORT, swkey->eth.in_port);
+ if (swkey->eth.in_port != USHRT_MAX)
+ NLA_PUT_U32(skb, OVS_KEY_ATTR_IN_PORT, swkey->eth.in_port);
nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
if (!nla)
struct sw_flow_key {
struct {
__be64 tun_id; /* Encapsulating tunnel ID. */
- u16 in_port; /* Input switch port. */
+ u16 in_port; /* Input switch port (or USHRT_MAX). */
u8 src[ETH_ALEN]; /* Ethernet source address. */
u8 dst[ETH_ALEN]; /* Ethernet destination address. */
__be16 tci; /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
return EINVAL;
}
+ if (flow->in_port < OFPP_MAX
+ ? flow->in_port >= MAX_PORTS
+ : flow->in_port != OFPP_LOCAL && flow->in_port != OFPP_NONE) {
+ return EINVAL;
+ }
+
return 0;
}
}
flow_extract(©, 0, -1, &key);
- dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key);
-
- error = dp_netdev_execute_actions(dp, ©, &key, actions, actions_len);
+ error = dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key);
+ if (!error) {
+ error = dp_netdev_execute_actions(dp, ©, &key,
+ actions, actions_len);
+ }
if (mutates) {
ofpbuf_uninit(©);
}
nl_msg_put_be64(buf, OVS_KEY_ATTR_TUN_ID, flow->tun_id);
}
- nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT,
- ofp_port_to_odp_port(flow->in_port));
+ if (flow->in_port != OFPP_NONE) {
+ nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT,
+ ofp_port_to_odp_port(flow->in_port));
+ }
eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
sizeof *eth_key);
memset(flow, 0, sizeof *flow);
flow->dl_type = htons(FLOW_DL_TYPE_NONE);
+ flow->in_port = OFPP_NONE;
prev_type = OVS_KEY_ATTR_UNSPEC;
NL_ATTR_FOR_EACH (nla, left, key, key_len) {
flow->in_port = odp_port_to_ofp_port(nl_attr_get_u32(nla));
break;
+ case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_ETHERNET):
+ case TRANSITION(OVS_KEY_ATTR_TUN_ID, OVS_KEY_ATTR_ETHERNET):
case TRANSITION(OVS_KEY_ATTR_IN_PORT, OVS_KEY_ATTR_ETHERNET):
eth_key = nl_attr_get(nla);
memcpy(flow->dl_src, eth_key->eth_src, ETH_ADDR_LEN);