The presence of a layer 3 packet is signaled by the absence of OVS_KEY_ATTR_ETHERNET in the packet metadata passed from user space.
Signed-off-by: Lorand Jakab <loja...@cisco.com> --- datapath/datapath.c | 29 +++++++++++++++++------------ datapath/flow.c | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 3607170..3ecb3cc 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -547,18 +547,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len); - skb_reset_mac_header(packet); - eth = eth_hdr(packet); - - /* 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) >= ETH_P_802_3_MIN) - packet->protocol = eth->h_proto; - else - packet->protocol = htons(ETH_P_802_2); - /* Build an sw_flow for sending this packet. */ flow = ovs_flow_alloc(); err = PTR_ERR(flow); @@ -570,6 +558,23 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) if (err) goto err_flow_free; + skb_reset_mac_header(packet); + + if (flow->key.phy.is_layer3) { + skb_reset_network_header(packet); + } else { + eth = eth_hdr(packet); + + /* 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) >= ETH_P_802_3_MIN) + packet->protocol = eth->h_proto; + else + packet->protocol = htons(ETH_P_802_2); + } + err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], &flow->key, &acts, log); if (err) diff --git a/datapath/flow.c b/datapath/flow.c index b01f7bd..1dd3ac8 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -353,6 +353,18 @@ static __be16 parse_ethertype(struct sk_buff *skb) return htons(ETH_P_802_2); } +static __be16 ethertype_from_ip_version(struct sk_buff *skb) +{ + struct iphdr *iphdr = ip_hdr(skb); + + if (iphdr->version == 4) + return htons(ETH_P_IP); + else if (iphdr->version == 6) + return htons(ETH_P_IPV6); + + return 0; +} + static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, int nh_len) { @@ -461,8 +473,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) /* Link layer. */ if (key->phy.is_layer3) { + skb_reset_network_header(skb); + key->eth.tci = 0; - key->eth.type = skb->protocol; + key->eth.type = ethertype_from_ip_version(skb); } else { eth = eth_hdr(skb); ether_addr_copy(key->eth.src, eth->h_source); @@ -483,9 +497,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) key->eth.type = parse_ethertype(skb); if (unlikely(key->eth.type == htons(0))) return -ENOMEM; + + skb_reset_network_header(skb); } - skb_reset_network_header(skb); skb_reset_mac_len(skb); __skb_push(skb, skb->data - skb_mac_header(skb)); -- 1.9.3 (Apple Git-50) _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev