Skip to content

Commit 22117b3

Browse files
committed
Merge branch 'vxlan-gro-fixes'
Jiri Benc says: ==================== vxlan: fix GRO with VXLAN-GPE The first patch generalizes code for the second patch, which is a fix for broken VXLAN-GPE GRO. Thanks to Paolo for noticing the bug. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 8d01da0 + b0b672c commit 22117b3

File tree

1 file changed

+97
-45
lines changed

1 file changed

+97
-45
lines changed

drivers/net/vxlan/vxlan_core.c

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,32 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
623623
return 1;
624624
}
625625

626+
static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
627+
{
628+
struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
629+
630+
/* Need to have Next Protocol set for interfaces in GPE mode. */
631+
if (!gpe->np_applied)
632+
return false;
633+
/* "The initial version is 0. If a receiver does not support the
634+
* version indicated it MUST drop the packet.
635+
*/
636+
if (gpe->version != 0)
637+
return false;
638+
/* "When the O bit is set to 1, the packet is an OAM packet and OAM
639+
* processing MUST occur." However, we don't implement OAM
640+
* processing, thus drop the packet.
641+
*/
642+
if (gpe->oam_flag)
643+
return false;
644+
645+
*protocol = tun_p_to_eth_p(gpe->next_protocol);
646+
if (!*protocol)
647+
return false;
648+
649+
return true;
650+
}
651+
626652
static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
627653
unsigned int off,
628654
struct vxlanhdr *vh, size_t hdrlen,
@@ -649,39 +675,37 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
649675
return vh;
650676
}
651677

652-
static struct sk_buff *vxlan_gro_receive(struct sock *sk,
653-
struct list_head *head,
654-
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)
655682
{
656-
struct sk_buff *pp = NULL;
657683
struct sk_buff *p;
658684
struct vxlanhdr *vh, *vh2;
659685
unsigned int hlen, off_vx;
660-
int flush = 1;
661686
struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
662687
__be32 flags;
663-
struct gro_remcsum grc;
664688

665-
skb_gro_remcsum_init(&grc);
689+
skb_gro_remcsum_init(grc);
666690

667691
off_vx = skb_gro_offset(skb);
668692
hlen = off_vx + sizeof(*vh);
669693
vh = skb_gro_header(skb, hlen, off_vx);
670694
if (unlikely(!vh))
671-
goto out;
695+
return NULL;
672696

673697
skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
674698

675699
flags = vh->vx_flags;
676700

677701
if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
678702
vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
679-
vh->vx_vni, &grc,
703+
vh->vx_vni, grc,
680704
!!(vs->flags &
681705
VXLAN_F_REMCSUM_NOPARTIAL));
682706

683707
if (!vh)
684-
goto out;
708+
return NULL;
685709
}
686710

687711
skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
@@ -698,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
698722
}
699723
}
700724

701-
pp = call_gro_receive(eth_gro_receive, head, skb);
702-
flush = 0;
725+
return vh;
726+
}
703727

704-
out:
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;
735+
736+
if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
737+
pp = call_gro_receive(eth_gro_receive, head, skb);
738+
flush = 0;
739+
}
705740
skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
741+
return pp;
742+
}
743+
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;
706754

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);
707767
return pp;
708768
}
709769

@@ -715,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
715775
return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
716776
}
717777

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+
718793
static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
719794
__u16 state, __be32 src_vni,
720795
__u16 ndm_flags)
@@ -1525,35 +1600,6 @@ static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
15251600
unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
15261601
}
15271602

1528-
static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
1529-
__be16 *protocol,
1530-
struct sk_buff *skb, u32 vxflags)
1531-
{
1532-
struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
1533-
1534-
/* Need to have Next Protocol set for interfaces in GPE mode. */
1535-
if (!gpe->np_applied)
1536-
return false;
1537-
/* "The initial version is 0. If a receiver does not support the
1538-
* version indicated it MUST drop the packet.
1539-
*/
1540-
if (gpe->version != 0)
1541-
return false;
1542-
/* "When the O bit is set to 1, the packet is an OAM packet and OAM
1543-
* processing MUST occur." However, we don't implement OAM
1544-
* processing, thus drop the packet.
1545-
*/
1546-
if (gpe->oam_flag)
1547-
return false;
1548-
1549-
*protocol = tun_p_to_eth_p(gpe->next_protocol);
1550-
if (!*protocol)
1551-
return false;
1552-
1553-
unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
1554-
return true;
1555-
}
1556-
15571603
static bool vxlan_set_mac(struct vxlan_dev *vxlan,
15581604
struct vxlan_sock *vs,
15591605
struct sk_buff *skb, __be32 vni)
@@ -1655,8 +1701,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
16551701
* used by VXLAN extensions if explicitly requested.
16561702
*/
16571703
if (vs->flags & VXLAN_F_GPE) {
1658-
if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
1704+
if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
16591705
goto drop;
1706+
unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
16601707
raw_proto = true;
16611708
}
16621709

@@ -3378,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
33783425
tunnel_cfg.encap_rcv = vxlan_rcv;
33793426
tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
33803427
tunnel_cfg.encap_destroy = NULL;
3381-
tunnel_cfg.gro_receive = vxlan_gro_receive;
3382-
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+
}
33833435

33843436
setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
33853437

0 commit comments

Comments
 (0)