aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJiri Benc <jbenc@redhat.com>2016-11-10 10:28:19 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-13 00:51:02 -0500
commite2d9d8358cb961340ef88620b6a25ba4557033d5 (patch)
treec2735d79cdbe2eb2919d41939d3f575648e50b30 /net/openvswitch
parent329f45bc4f191c663dc156c510816411a4310578 (diff)
openvswitch: pass mac_proto to ovs_vport_send
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>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c29
-rw-r--r--net/openvswitch/vport.c2
-rw-r--r--net/openvswitch/vport.h2
3 files changed, 19 insertions, 14 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 44144f914920..dc8bb97e2258 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -66,6 +66,7 @@ struct ovs_frag_data {
66 u16 vlan_tci; 66 u16 vlan_tci;
67 __be16 vlan_proto; 67 __be16 vlan_proto;
68 unsigned int l2_len; 68 unsigned int l2_len;
69 u8 mac_proto;
69 u8 l2_data[MAX_L2_LEN]; 70 u8 l2_data[MAX_L2_LEN];
70}; 71};
71 72
@@ -673,7 +674,7 @@ static int ovs_vport_output(struct net *net, struct sock *sk, struct sk_buff *sk
673 skb_reset_mac_len(skb); 674 skb_reset_mac_len(skb);
674 } 675 }
675 676
676 ovs_vport_send(vport, skb); 677 ovs_vport_send(vport, skb, data->mac_proto);
677 return 0; 678 return 0;
678} 679}
679 680
@@ -692,7 +693,7 @@ static struct dst_ops ovs_dst_ops = {
692 * ovs_vport_output(), which is called once per fragmented packet. 693 * ovs_vport_output(), which is called once per fragmented packet.
693 */ 694 */
694static void prepare_frag(struct vport *vport, struct sk_buff *skb, 695static void prepare_frag(struct vport *vport, struct sk_buff *skb,
695 u16 orig_network_offset) 696 u16 orig_network_offset, u8 mac_proto)
696{ 697{
697 unsigned int hlen = skb_network_offset(skb); 698 unsigned int hlen = skb_network_offset(skb);
698 struct ovs_frag_data *data; 699 struct ovs_frag_data *data;
@@ -705,6 +706,7 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb,
705 data->network_offset = orig_network_offset; 706 data->network_offset = orig_network_offset;
706 data->vlan_tci = skb->vlan_tci; 707 data->vlan_tci = skb->vlan_tci;
707 data->vlan_proto = skb->vlan_proto; 708 data->vlan_proto = skb->vlan_proto;
709 data->mac_proto = mac_proto;
708 data->l2_len = hlen; 710 data->l2_len = hlen;
709 memcpy(&data->l2_data, skb->data, hlen); 711 memcpy(&data->l2_data, skb->data, hlen);
710 712
@@ -713,7 +715,8 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb,
713} 715}
714 716
715static void ovs_fragment(struct net *net, struct vport *vport, 717static void ovs_fragment(struct net *net, struct vport *vport,
716 struct sk_buff *skb, u16 mru, __be16 ethertype) 718 struct sk_buff *skb, u16 mru,
719 struct sw_flow_key *key)
717{ 720{
718 u16 orig_network_offset = 0; 721 u16 orig_network_offset = 0;
719 722
@@ -727,11 +730,12 @@ static void ovs_fragment(struct net *net, struct vport *vport,
727 goto err; 730 goto err;
728 } 731 }
729 732
730 if (ethertype == htons(ETH_P_IP)) { 733 if (key->eth.type == htons(ETH_P_IP)) {
731 struct dst_entry ovs_dst; 734 struct dst_entry ovs_dst;
732 unsigned long orig_dst; 735 unsigned long orig_dst;
733 736
734 prepare_frag(vport, skb, orig_network_offset); 737 prepare_frag(vport, skb, orig_network_offset,
738 ovs_key_mac_proto(key));
735 dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1, 739 dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1,
736 DST_OBSOLETE_NONE, DST_NOCOUNT); 740 DST_OBSOLETE_NONE, DST_NOCOUNT);
737 ovs_dst.dev = vport->dev; 741 ovs_dst.dev = vport->dev;
@@ -742,7 +746,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
742 746
743 ip_do_fragment(net, skb->sk, skb, ovs_vport_output); 747 ip_do_fragment(net, skb->sk, skb, ovs_vport_output);
744 refdst_drop(orig_dst); 748 refdst_drop(orig_dst);
745 } else if (ethertype == htons(ETH_P_IPV6)) { 749 } else if (key->eth.type == htons(ETH_P_IPV6)) {
746 const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); 750 const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
747 unsigned long orig_dst; 751 unsigned long orig_dst;
748 struct rt6_info ovs_rt; 752 struct rt6_info ovs_rt;
@@ -751,7 +755,8 @@ static void ovs_fragment(struct net *net, struct vport *vport,
751 goto err; 755 goto err;
752 } 756 }
753 757
754 prepare_frag(vport, skb, orig_network_offset); 758 prepare_frag(vport, skb, orig_network_offset,
759 ovs_key_mac_proto(key));
755 memset(&ovs_rt, 0, sizeof(ovs_rt)); 760 memset(&ovs_rt, 0, sizeof(ovs_rt));
756 dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1, 761 dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1,
757 DST_OBSOLETE_NONE, DST_NOCOUNT); 762 DST_OBSOLETE_NONE, DST_NOCOUNT);
@@ -765,7 +770,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
765 refdst_drop(orig_dst); 770 refdst_drop(orig_dst);
766 } else { 771 } else {
767 WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.", 772 WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
768 ovs_vport_name(vport), ntohs(ethertype), mru, 773 ovs_vport_name(vport), ntohs(key->eth.type), mru,
769 vport->dev->mtu); 774 vport->dev->mtu);
770 goto err; 775 goto err;
771 } 776 }
@@ -785,19 +790,19 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
785 u32 cutlen = OVS_CB(skb)->cutlen; 790 u32 cutlen = OVS_CB(skb)->cutlen;
786 791
787 if (unlikely(cutlen > 0)) { 792 if (unlikely(cutlen > 0)) {
788 if (skb->len - cutlen > ETH_HLEN) 793 if (skb->len - cutlen > ovs_mac_header_len(key))
789 pskb_trim(skb, skb->len - cutlen); 794 pskb_trim(skb, skb->len - cutlen);
790 else 795 else
791 pskb_trim(skb, ETH_HLEN); 796 pskb_trim(skb, ovs_mac_header_len(key));
792 } 797 }
793 798
794 if (likely(!mru || 799 if (likely(!mru ||
795 (skb->len <= mru + vport->dev->hard_header_len))) { 800 (skb->len <= mru + vport->dev->hard_header_len))) {
796 ovs_vport_send(vport, skb); 801 ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
797 } else if (mru <= vport->dev->mtu) { 802 } else if (mru <= vport->dev->mtu) {
798 struct net *net = read_pnet(&dp->net); 803 struct net *net = read_pnet(&dp->net);
799 804
800 ovs_fragment(net, vport, skb, mru, key->eth.type); 805 ovs_fragment(net, vport, skb, mru, key);
801 } else { 806 } else {
802 kfree_skb(skb); 807 kfree_skb(skb);
803 } 808 }
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 3e131f6868f2..898ed377b5cc 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -481,7 +481,7 @@ static unsigned int packet_length(const struct sk_buff *skb,
481 return length; 481 return length;
482} 482}
483 483
484void ovs_vport_send(struct vport *vport, struct sk_buff *skb) 484void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
485{ 485{
486 int mtu = vport->dev->mtu; 486 int mtu = vport->dev->mtu;
487 487
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 46e5b69927c7..cda66c26ad08 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -197,6 +197,6 @@ int __ovs_vport_ops_register(struct vport_ops *ops);
197 }) 197 })
198 198
199void ovs_vport_ops_unregister(struct vport_ops *ops); 199void ovs_vport_ops_unregister(struct vport_ops *ops);
200void ovs_vport_send(struct vport *vport, struct sk_buff *skb); 200void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto);
201 201
202#endif /* vport.h */ 202#endif /* vport.h */