openvswitch: pass mac_proto to ovs_vport_send
authorJiri Benc <jbenc@redhat.com>
Thu, 10 Nov 2016 15:28:19 +0000 (16:28 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 13 Nov 2016 05:51:02 +0000 (00:51 -0500)
We'll need it to alter packets sent to ARPHRD_NONE interfaces.

Change do_output() to use the actual L2 header size of the packet when
deciding on the minimum cutlen. The assumption here is that what matters is
not the output interface hard_header_len but rather the L2 header of the
particular packet. For example, ARPHRD_NONE tunnels that encapsulate
Ethernet should get at least the Ethernet header.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/openvswitch/actions.c
net/openvswitch/vport.c
net/openvswitch/vport.h

index 44144f914920a4f8ba0229db64fdf78187540195..dc8bb97e22585d559c7c306fbc9b8c1d9b3e520c 100644 (file)
@@ -66,6 +66,7 @@ struct ovs_frag_data {
        u16 vlan_tci;
        __be16 vlan_proto;
        unsigned int l2_len;
+       u8 mac_proto;
        u8 l2_data[MAX_L2_LEN];
 };
 
@@ -673,7 +674,7 @@ static int ovs_vport_output(struct net *net, struct sock *sk, struct sk_buff *sk
                skb_reset_mac_len(skb);
        }
 
-       ovs_vport_send(vport, skb);
+       ovs_vport_send(vport, skb, data->mac_proto);
        return 0;
 }
 
@@ -692,7 +693,7 @@ static struct dst_ops ovs_dst_ops = {
  * ovs_vport_output(), which is called once per fragmented packet.
  */
 static void prepare_frag(struct vport *vport, struct sk_buff *skb,
-                        u16 orig_network_offset)
+                        u16 orig_network_offset, u8 mac_proto)
 {
        unsigned int hlen = skb_network_offset(skb);
        struct ovs_frag_data *data;
@@ -705,6 +706,7 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb,
        data->network_offset = orig_network_offset;
        data->vlan_tci = skb->vlan_tci;
        data->vlan_proto = skb->vlan_proto;
+       data->mac_proto = mac_proto;
        data->l2_len = hlen;
        memcpy(&data->l2_data, skb->data, hlen);
 
@@ -713,7 +715,8 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb,
 }
 
 static void ovs_fragment(struct net *net, struct vport *vport,
-                        struct sk_buff *skb, u16 mru, __be16 ethertype)
+                        struct sk_buff *skb, u16 mru,
+                        struct sw_flow_key *key)
 {
        u16 orig_network_offset = 0;
 
@@ -727,11 +730,12 @@ static void ovs_fragment(struct net *net, struct vport *vport,
                goto err;
        }
 
-       if (ethertype == htons(ETH_P_IP)) {
+       if (key->eth.type == htons(ETH_P_IP)) {
                struct dst_entry ovs_dst;
                unsigned long orig_dst;
 
-               prepare_frag(vport, skb, orig_network_offset);
+               prepare_frag(vport, skb, orig_network_offset,
+                            ovs_key_mac_proto(key));
                dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1,
                         DST_OBSOLETE_NONE, DST_NOCOUNT);
                ovs_dst.dev = vport->dev;
@@ -742,7 +746,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
 
                ip_do_fragment(net, skb->sk, skb, ovs_vport_output);
                refdst_drop(orig_dst);
-       } else if (ethertype == htons(ETH_P_IPV6)) {
+       } else if (key->eth.type == htons(ETH_P_IPV6)) {
                const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
                unsigned long orig_dst;
                struct rt6_info ovs_rt;
@@ -751,7 +755,8 @@ static void ovs_fragment(struct net *net, struct vport *vport,
                        goto err;
                }
 
-               prepare_frag(vport, skb, orig_network_offset);
+               prepare_frag(vport, skb, orig_network_offset,
+                            ovs_key_mac_proto(key));
                memset(&ovs_rt, 0, sizeof(ovs_rt));
                dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1,
                         DST_OBSOLETE_NONE, DST_NOCOUNT);
@@ -765,7 +770,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
                refdst_drop(orig_dst);
        } else {
                WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
-                         ovs_vport_name(vport), ntohs(ethertype), mru,
+                         ovs_vport_name(vport), ntohs(key->eth.type), mru,
                          vport->dev->mtu);
                goto err;
        }
@@ -785,19 +790,19 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
                u32 cutlen = OVS_CB(skb)->cutlen;
 
                if (unlikely(cutlen > 0)) {
-                       if (skb->len - cutlen > ETH_HLEN)
+                       if (skb->len - cutlen > ovs_mac_header_len(key))
                                pskb_trim(skb, skb->len - cutlen);
                        else
-                               pskb_trim(skb, ETH_HLEN);
+                               pskb_trim(skb, ovs_mac_header_len(key));
                }
 
                if (likely(!mru ||
                           (skb->len <= mru + vport->dev->hard_header_len))) {
-                       ovs_vport_send(vport, skb);
+                       ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
                } else if (mru <= vport->dev->mtu) {
                        struct net *net = read_pnet(&dp->net);
 
-                       ovs_fragment(net, vport, skb, mru, key->eth.type);
+                       ovs_fragment(net, vport, skb, mru, key);
                } else {
                        kfree_skb(skb);
                }
index 3e131f6868f28ad6028aed3bd483ffbd956eb3fb..898ed377b5ccab0bf532d81ef357c4afdc720d09 100644 (file)
@@ -481,7 +481,7 @@ static unsigned int packet_length(const struct sk_buff *skb,
        return length;
 }
 
-void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
+void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
 {
        int mtu = vport->dev->mtu;
 
index 46e5b69927c72f9cec5c5d32034120ad87439961..cda66c26ad0889a0d7ef99b5e14b2f83e4e2ff11 100644 (file)
@@ -197,6 +197,6 @@ int __ovs_vport_ops_register(struct vport_ops *ops);
        })
 
 void ovs_vport_ops_unregister(struct vport_ops *ops);
-void ovs_vport_send(struct vport *vport, struct sk_buff *skb);
+void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto);
 
 #endif /* vport.h */