From a393b897f27405592dc56f7084796c8bf1815519 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Fri, 4 Sep 2009 17:03:22 -0700 Subject: datapath: Don't drop MTU-sized VLAN packets from userspace Before transimitting a packet, the datapath checks that the packet length is not greater than the MTU. It determines the length based on the 'protocol' field in the skb. If 'protocol' is ETH_P_8021Q, it reduces the packet length as stored in the 'len' field by four bytes, which is the size of a VLAN tag header. Unfortunately, packets that arrived from userspace were not having the 'protocol' field set, which would cause MTU-sized packets to be dropped. This commit sets the 'protocol' field appropriately. Thanks to Ben Pfaff for the help diagnosing this issue. NIC-17 and NIC-26 --- datapath/datapath.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'datapath') diff --git a/datapath/datapath.c b/datapath/datapath.c index 14602152..b0dbe7fc 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1127,6 +1127,7 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep) struct odp_flow_key key; struct sk_buff *skb; struct sw_flow_actions *actions; + struct ethhdr *eth; int err; err = -EFAULT; @@ -1166,6 +1167,17 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep) execute.length)) goto error_free_skb; + skb_reset_mac_header(skb); + eth = eth_hdr(skb); + + /* Normally, setting the skb 'protocol' field would be handled by a + * call to eth_type_trans(), but it assumes there's a sending + * device, which we may not have. */ + if (ntohs(eth->h_proto) >= 1536) + skb->protocol = eth->h_proto; + else + skb->protocol = htons(ETH_P_802_2); + flow_extract(skb, execute.in_port, &key); err = execute_actions(dp, skb, &key, actions->actions, actions->n_actions, GFP_KERNEL); -- cgit v1.2.3