diff options
| author | Ben Pfaff <blp@nicira.com> | 2011-09-08 16:30:20 -0700 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2011-09-08 16:30:20 -0700 |
| commit | 18886b60bc7face9e08bc7ef06da365ee5c39e0a (patch) | |
| tree | afa53c577dde76aaffb160626787ee0c1785d9b9 /datapath | |
| parent | 0fe255dfbf37fa7ddc23c2593c512c092b0f61d7 (diff) | |
| download | openvswitch-18886b60bc7face9e08bc7ef06da365ee5c39e0a.tar.gz | |
datapath: Allow a packet with no input port to omit OVS_KEY_ATTR_IN_PORT.
When ovs-vswitchd executes actions on a synthesized packet, that is, on a
packet that is not being forwarded from any particular port but is being
generated by ovs-vswitchd itself or by an OpenFlow controller (using a
OFPT_PACKET_OUT message with an in_port of OFPP_NONE), there is no good
choice for the in_port to pass to the kernel in the flow in the
OVS_PACKET_CMD_EXECUTE message. This commit allows ovs-vswitchd to omit
the in_port entirely in this case.
This fixes a bug in OFPT_PACKET_OUT: using an in_port of OFPP_NONE would
cause the packet to be dropped by the kernel, since that's an invalid
input port.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Reported-by: Aaron Rosen <arosen@clemson.edu>
Diffstat (limited to 'datapath')
| -rw-r--r-- | datapath/flow.c | 16 | ||||
| -rw-r--r-- | datapath/flow.h | 2 |
2 files changed, 9 insertions, 9 deletions
diff --git a/datapath/flow.c b/datapath/flow.c index 9d7fbc9b9..e091f5017 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -624,7 +624,7 @@ static const u32 key_lens[OVS_KEY_ATTR_MAX + 1] = { * 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, @@ -637,6 +637,7 @@ 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); @@ -671,6 +672,8 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, 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); @@ -888,6 +891,7 @@ int flow_metadata_from_nlattrs(u16 *in_port, __be64 *tun_id, u16 prev_type; int rem; + *in_port = USHRT_MAX; *tun_id = 0; prev_type = OVS_KEY_ATTR_UNSPEC; @@ -910,18 +914,13 @@ int flow_metadata_from_nlattrs(u16 *in_port, __be64 *tun_id, 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; } @@ -938,7 +937,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) 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) diff --git a/datapath/flow.h b/datapath/flow.h index 997692c58..c7a022c96 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -33,7 +33,7 @@ struct sw_flow_actions { 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. */ |
