@@ -675,39 +675,37 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
675675 return vh ;
676676}
677677
678- static struct sk_buff * vxlan_gro_receive (struct sock * sk ,
679- struct list_head * head ,
680- struct sk_buff * skb )
678+ static struct vxlanhdr * vxlan_gro_prepare_receive (struct sock * sk ,
679+ struct list_head * head ,
680+ struct sk_buff * skb ,
681+ struct gro_remcsum * grc )
681682{
682- struct sk_buff * pp = NULL ;
683683 struct sk_buff * p ;
684684 struct vxlanhdr * vh , * vh2 ;
685685 unsigned int hlen , off_vx ;
686- int flush = 1 ;
687686 struct vxlan_sock * vs = rcu_dereference_sk_user_data (sk );
688687 __be32 flags ;
689- struct gro_remcsum grc ;
690688
691- skb_gro_remcsum_init (& grc );
689+ skb_gro_remcsum_init (grc );
692690
693691 off_vx = skb_gro_offset (skb );
694692 hlen = off_vx + sizeof (* vh );
695693 vh = skb_gro_header (skb , hlen , off_vx );
696694 if (unlikely (!vh ))
697- goto out ;
695+ return NULL ;
698696
699697 skb_gro_postpull_rcsum (skb , vh , sizeof (struct vxlanhdr ));
700698
701699 flags = vh -> vx_flags ;
702700
703701 if ((flags & VXLAN_HF_RCO ) && (vs -> flags & VXLAN_F_REMCSUM_RX )) {
704702 vh = vxlan_gro_remcsum (skb , off_vx , vh , sizeof (struct vxlanhdr ),
705- vh -> vx_vni , & grc ,
703+ vh -> vx_vni , grc ,
706704 !!(vs -> flags &
707705 VXLAN_F_REMCSUM_NOPARTIAL ));
708706
709707 if (!vh )
710- goto out ;
708+ return NULL ;
711709 }
712710
713711 skb_gro_pull (skb , sizeof (struct vxlanhdr )); /* pull vxlan header */
@@ -724,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
724722 }
725723 }
726724
727- pp = call_gro_receive (eth_gro_receive , head , skb );
728- flush = 0 ;
725+ return vh ;
726+ }
727+
728+ static struct sk_buff * vxlan_gro_receive (struct sock * sk ,
729+ struct list_head * head ,
730+ struct sk_buff * skb )
731+ {
732+ struct sk_buff * pp = NULL ;
733+ struct gro_remcsum grc ;
734+ int flush = 1 ;
729735
730- out :
736+ if (vxlan_gro_prepare_receive (sk , head , skb , & grc )) {
737+ pp = call_gro_receive (eth_gro_receive , head , skb );
738+ flush = 0 ;
739+ }
731740 skb_gro_flush_final_remcsum (skb , pp , flush , & grc );
741+ return pp ;
742+ }
732743
744+ static struct sk_buff * vxlan_gpe_gro_receive (struct sock * sk ,
745+ struct list_head * head ,
746+ struct sk_buff * skb )
747+ {
748+ const struct packet_offload * ptype ;
749+ struct sk_buff * pp = NULL ;
750+ struct gro_remcsum grc ;
751+ struct vxlanhdr * vh ;
752+ __be16 protocol ;
753+ int flush = 1 ;
754+
755+ vh = vxlan_gro_prepare_receive (sk , head , skb , & grc );
756+ if (vh ) {
757+ if (!vxlan_parse_gpe_proto (vh , & protocol ))
758+ goto out ;
759+ ptype = gro_find_receive_by_type (protocol );
760+ if (!ptype )
761+ goto out ;
762+ pp = call_gro_receive (ptype -> callbacks .gro_receive , head , skb );
763+ flush = 0 ;
764+ }
765+ out :
766+ skb_gro_flush_final_remcsum (skb , pp , flush , & grc );
733767 return pp ;
734768}
735769
@@ -741,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
741775 return eth_gro_complete (skb , nhoff + sizeof (struct vxlanhdr ));
742776}
743777
778+ static int vxlan_gpe_gro_complete (struct sock * sk , struct sk_buff * skb , int nhoff )
779+ {
780+ struct vxlanhdr * vh = (struct vxlanhdr * )(skb -> data + nhoff );
781+ const struct packet_offload * ptype ;
782+ int err = - ENOSYS ;
783+ __be16 protocol ;
784+
785+ if (!vxlan_parse_gpe_proto (vh , & protocol ))
786+ return err ;
787+ ptype = gro_find_complete_by_type (protocol );
788+ if (ptype )
789+ err = ptype -> callbacks .gro_complete (skb , nhoff + sizeof (struct vxlanhdr ));
790+ return err ;
791+ }
792+
744793static struct vxlan_fdb * vxlan_fdb_alloc (struct vxlan_dev * vxlan , const u8 * mac ,
745794 __u16 state , __be32 src_vni ,
746795 __u16 ndm_flags )
@@ -3376,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
33763425 tunnel_cfg .encap_rcv = vxlan_rcv ;
33773426 tunnel_cfg .encap_err_lookup = vxlan_err_lookup ;
33783427 tunnel_cfg .encap_destroy = NULL ;
3379- tunnel_cfg .gro_receive = vxlan_gro_receive ;
3380- tunnel_cfg .gro_complete = vxlan_gro_complete ;
3428+ if (vs -> flags & VXLAN_F_GPE ) {
3429+ tunnel_cfg .gro_receive = vxlan_gpe_gro_receive ;
3430+ tunnel_cfg .gro_complete = vxlan_gpe_gro_complete ;
3431+ } else {
3432+ tunnel_cfg .gro_receive = vxlan_gro_receive ;
3433+ tunnel_cfg .gro_complete = vxlan_gro_complete ;
3434+ }
33813435
33823436 setup_udp_tunnel_sock (net , sock , & tunnel_cfg );
33833437
0 commit comments