This is used by openvswitch for building vxlan packet.
Signed-off-by: Pravin B Shelar <[email protected]>
---
drivers/net/vxlan.c | 72 +++++++++++++++++++++++++++++++-------------------
include/net/vxlan.h | 3 ++
2 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index a17a7cb..11c1f69 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -909,10 +909,17 @@ static void vxlan_set_owner(const struct vxlan_port
*port, struct sk_buff *skb)
static int handle_offloads(struct sk_buff *skb)
{
+ if (!skb->encapsulation) {
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+ }
+
if (skb_is_gso(skb)) {
int err = skb_unclone(skb, GFP_ATOMIC);
- if (unlikely(err))
+ if (unlikely(err)) {
+ kfree_skb(skb);
return err;
+ }
skb_shinfo(skb)->gso_type |= (SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP);
} else if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -921,6 +928,38 @@ static int handle_offloads(struct sk_buff *skb)
return 0;
}
+struct sk_buff *vxlan_build_header(const struct vxlan_port *port,
+ __u16 src_port, struct sk_buff *skb,
+ __be32 vni)
+{
+ struct vxlanhdr *vxh;
+ struct udphdr *uh;
+ int err;
+
+ err = handle_offloads(skb);
+ if (err)
+ return NULL;
+
+ vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
+ vxh->vx_flags = htonl(VXLAN_FLAGS);
+ vxh->vx_vni = vni;
+
+ __skb_push(skb, sizeof(*uh));
+ skb_reset_transport_header(skb);
+ uh = udp_hdr(skb);
+
+ uh->dest = port->portno;
+ uh->source = htons(src_port);
+
+ uh->len = htons(skb->len);
+ uh->check = 0;
+
+ vxlan_set_owner(port, skb);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(vxlan_build_header);
+
static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct vxlan_rdst *rdst, bool did_rsc)
{
@@ -929,8 +968,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb,
struct net_device *dev,
struct rtable *rt;
const struct iphdr *old_iph;
struct iphdr *iph;
- struct vxlanhdr *vxh;
- struct udphdr *uh;
struct flowi4 fl4;
unsigned int pkt_len = skb->len;
__be32 dst;
@@ -966,11 +1003,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb,
struct net_device *dev,
goto drop;
}
- if (!skb->encapsulation) {
- skb_reset_inner_headers(skb);
- skb->encapsulation = 1;
- }
-
/* Need space for new headers (invalidates iph ptr) */
if (skb_cow_head(skb, VXLAN_HEADROOM))
goto drop;
@@ -985,7 +1017,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb,
struct net_device *dev,
if (tos == 1)
tos = ip_tunnel_get_dsfield(old_iph, skb);
- src_port = tunnel_src_port(vxlan->port_max, vxlan->port_min, skb);
memset(&fl4, 0, sizeof(fl4));
fl4.flowi4_oif = rdst->remote_ifindex;
@@ -1013,19 +1044,11 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb,
struct net_device *dev,
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
- vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
- vxh->vx_flags = htonl(VXLAN_FLAGS);
- vxh->vx_vni = htonl(vni << 8);
-
- __skb_push(skb, sizeof(*uh));
- skb_reset_transport_header(skb);
- uh = udp_hdr(skb);
-
- uh->dest = htons(dst_port);
- uh->source = htons(src_port);
-
- uh->len = htons(skb->len);
- uh->check = 0;
+ src_port = tunnel_src_port(vxlan->port_max, vxlan->port_min, skb);
+ skb = vxlan_build_header(&vn->port, src_port,
+ skb, htonl(vni << 8));
+ if (!skb)
+ goto drop;
__skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);
@@ -1042,11 +1065,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb,
struct net_device *dev,
nf_reset(skb);
- vxlan_set_owner(&vn->port, skb);
-
- if (handle_offloads(skb))
- goto drop;
-
iptunnel_xmit(skb, dev);
return NETDEV_TX_OK;
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index dae9619..237ccff 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -12,6 +12,9 @@ struct vxlan_port {
__be16 portno;
};
+struct sk_buff *vxlan_build_header(const struct vxlan_port *port,
+ __u16 src_port,
+ struct sk_buff *skb, __be32 vni);
int vxlan_add_handler(struct net *net, struct vxlan_port *);
void vxlan_del_handler(struct net *net, const struct vxlan_port *port);
#endif
--
1.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev