Skip to content

Commit

Permalink
tunneling: Remove struct tnl_vport and tnl_ops.
Browse files Browse the repository at this point in the history
After flow based tunneling, kernel tunneling is greatly simplified.
There is no need to have extra tunneling layer between vport and
particular protocol.
Following patch removes tunneling struct which make code easy to read.

Signed-off-by: Pravin B Shelar <[email protected]>
Acked-by: Jesse Gross <[email protected]>
  • Loading branch information
Pravin B Shelar committed May 6, 2013
1 parent 2f52420 commit c405d28
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 330 deletions.
104 changes: 28 additions & 76 deletions datapath/tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,27 +141,10 @@ static bool need_linearize(const struct sk_buff *skb)
return false;
}

static struct sk_buff *handle_offloads(struct sk_buff *skb,
const struct rtable *rt,
int tunnel_hlen)
static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
int min_headroom;
int err;

min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
+ tunnel_hlen
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);

if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
int head_delta = SKB_DATA_ALIGN(min_headroom -
skb_headroom(skb) +
16);
err = pskb_expand_head(skb, max_t(int, head_delta, 0),
0, GFP_ATOMIC);
if (unlikely(err))
goto error_free;
}

forward_ip_summed(skb, true);

if (skb_is_gso(skb)) {
Expand Down Expand Up @@ -218,33 +201,48 @@ u16 ovs_tnl_get_src_port(struct sk_buff *skb)
return (((u64) hash * range) >> 32) + low;
}

int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
u8 ipproto, int tunnel_hlen,
void (*build_header)(const struct vport *,
struct sk_buff *,
int tunnel_hlen))
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
int min_headroom;
struct rtable *rt;
__be32 saddr;
int sent_len = 0;
int tunnel_hlen;

if (unlikely(!OVS_CB(skb)->tun_key))
goto error_free;

/* Route lookup */
saddr = OVS_CB(skb)->tun_key->ipv4_src;
rt = find_route(ovs_dp_get_net(vport->dp),
&saddr,
OVS_CB(skb)->tun_key->ipv4_dst,
tnl_vport->tnl_ops->ipproto,
ipproto,
OVS_CB(skb)->tun_key->ipv4_tos,
skb_get_mark(skb));
if (IS_ERR(rt))
goto error_free;

/* Offloading */
tunnel_hlen = tnl_vport->tnl_ops->hdr_len(OVS_CB(skb)->tun_key);
tunnel_hlen += sizeof(struct iphdr);

skb = handle_offloads(skb, rt, tunnel_hlen);
min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
+ tunnel_hlen
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);

if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
int err;
int head_delta = SKB_DATA_ALIGN(min_headroom -
skb_headroom(skb) +
16);

err = pskb_expand_head(skb, max_t(int, head_delta, 0),
0, GFP_ATOMIC);
if (unlikely(err))
goto err_free_rt;
}

/* Offloading */
skb = handle_offloads(skb);
if (IS_ERR(skb)) {
skb = NULL;
goto err_free_rt;
Expand Down Expand Up @@ -278,13 +276,13 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
skb_dst_set(skb, &rt_dst(rt));

/* Push Tunnel header. */
tnl_vport->tnl_ops->build_header(vport, skb, tunnel_hlen);
build_header(vport, skb, tunnel_hlen);

/* Push IP header. */
iph = ip_hdr(skb);
iph->version = 4;
iph->ihl = sizeof(struct iphdr) >> 2;
iph->protocol = tnl_vport->tnl_ops->ipproto;
iph->protocol = ipproto;
iph->daddr = OVS_CB(skb)->tun_key->ipv4_dst;
iph->saddr = saddr;
iph->tos = OVS_CB(skb)->tun_key->ipv4_tos;
Expand Down Expand Up @@ -325,49 +323,3 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
return sent_len;
}

struct vport *ovs_tnl_create(const struct vport_parms *parms,
const struct vport_ops *vport_ops,
const struct tnl_ops *tnl_ops)
{
struct vport *vport;
struct tnl_vport *tnl_vport;
int err;

vport = ovs_vport_alloc(sizeof(struct tnl_vport), vport_ops, parms);
if (IS_ERR(vport)) {
err = PTR_ERR(vport);
goto error;
}

tnl_vport = tnl_vport_priv(vport);

strcpy(tnl_vport->name, parms->name);
tnl_vport->tnl_ops = tnl_ops;

return vport;

error:
return ERR_PTR(err);
}

static void free_port_rcu(struct rcu_head *rcu)
{
struct tnl_vport *tnl_vport = container_of(rcu,
struct tnl_vport, rcu);

ovs_vport_free(vport_from_priv(tnl_vport));
}

void ovs_tnl_destroy(struct vport *vport)
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);

call_rcu(&tnl_vport->rcu, free_port_rcu);
}

const char *ovs_tnl_get_name(const struct vport *vport)
{
const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
return tnl_vport->name;
}
39 changes: 5 additions & 34 deletions datapath/tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,16 @@
#include "flow.h"
#include "vport.h"

struct tnl_ops {
u8 ipproto; /* The IP protocol for the tunnel. */

/*
* Returns the length of the tunnel header that will be added in
* build_header() (i.e. excludes the IP header).
*/
int (*hdr_len)(const struct ovs_key_ipv4_tunnel *);
/*
* Builds header for given SKB. Space will have already been
* allocated at the start of the packet equal
* to sizeof(struct iphdr) + value returned by hdr_len().
*/
void (*build_header)(const struct vport *, struct sk_buff *,
int tunnel_hlen);
};
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
u8 ipproto, int tunnel_hlen,
void (*build_header)(const struct vport *,
struct sk_buff *,
int tunnel_hlen));

struct tnl_vport {
struct rcu_head rcu;

__be16 dst_port;
char name[IFNAMSIZ];
const struct tnl_ops *tnl_ops;
};

struct vport *ovs_tnl_create(const struct vport_parms *, const struct vport_ops *,
const struct tnl_ops *);
void ovs_tnl_destroy(struct vport *);

const char *ovs_tnl_get_name(const struct vport *vport);
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb);
void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb);
u16 ovs_tnl_get_src_port(struct sk_buff *skb);

static inline struct tnl_vport *tnl_vport_priv(const struct vport *vport)
{
return vport_priv(vport);
}

static inline void tnl_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
const struct iphdr *iph, __be64 tun_id, u32 tun_flags)
{
Expand Down
67 changes: 46 additions & 21 deletions datapath/vport-gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,10 @@ static void gre_exit(void)
inet_del_protocol(&gre_protocol_handlers, IPPROTO_GRE);
}

/* GRE vport. */
static const struct tnl_ops gre_tnl_ops = {
.ipproto = IPPROTO_GRE,
.hdr_len = gre_hdr_len,
.build_header = gre_build_header,
};
static const char *gre_get_name(const struct vport *vport)
{
return vport_priv(vport);
}

static struct vport *gre_create(const struct vport_parms *parms)
{
Expand All @@ -334,8 +332,11 @@ static struct vport *gre_create(const struct vport_parms *parms)
if (ovsl_dereference(ovs_net->vport_net.gre_vport))
return ERR_PTR(-EEXIST);

vport = ovs_tnl_create(parms, &ovs_gre_vport_ops, &gre_tnl_ops);
vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms);
if (IS_ERR(vport))
return vport;

strncpy(vport_priv(vport), parms->name, IFNAMSIZ);
rcu_assign_pointer(ovs_net->vport_net.gre_vport, vport);
return vport;
}
Expand All @@ -348,7 +349,21 @@ static void gre_tnl_destroy(struct vport *vport)
ovs_net = net_generic(net, ovs_net_id);

rcu_assign_pointer(ovs_net->vport_net.gre_vport, NULL);
ovs_tnl_destroy(vport);
ovs_vport_deferred_free(vport);
}

static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
{
int hlen;

if (unlikely(!OVS_CB(skb)->tun_key)) {
kfree_skb(skb);
ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
return 0;
}

hlen = gre_hdr_len(OVS_CB(skb)->tun_key);
return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre_build_header);
}

const struct vport_ops ovs_gre_vport_ops = {
Expand All @@ -358,17 +373,11 @@ const struct vport_ops ovs_gre_vport_ops = {
.exit = gre_exit,
.create = gre_create,
.destroy = gre_tnl_destroy,
.get_name = ovs_tnl_get_name,
.send = ovs_tnl_send,
.get_name = gre_get_name,
.send = gre_tnl_send,
};

/* GRE64 vport. */
static const struct tnl_ops gre64_tnl_ops = {
.ipproto = IPPROTO_GRE,
.hdr_len = gre64_hdr_len,
.build_header = gre64_build_header,
};

static struct vport *gre64_create(const struct vport_parms *parms)
{
struct net *net = ovs_dp_get_net(parms->dp);
Expand All @@ -379,13 +388,15 @@ static struct vport *gre64_create(const struct vport_parms *parms)
if (ovsl_dereference(ovs_net->vport_net.gre64_vport))
return ERR_PTR(-EEXIST);

vport = ovs_tnl_create(parms, &ovs_gre64_vport_ops, &gre64_tnl_ops);
vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre64_vport_ops, parms);
if (IS_ERR(vport))
return vport;

strncpy(vport_priv(vport), parms->name, IFNAMSIZ);
rcu_assign_pointer(ovs_net->vport_net.gre64_vport, vport);
return vport;
}


static void gre64_tnl_destroy(struct vport *vport)
{
struct net *net = ovs_dp_get_net(vport->dp);
Expand All @@ -394,7 +405,21 @@ static void gre64_tnl_destroy(struct vport *vport)
ovs_net = net_generic(net, ovs_net_id);

rcu_assign_pointer(ovs_net->vport_net.gre64_vport, NULL);
ovs_tnl_destroy(vport);
ovs_vport_deferred_free(vport);
}

static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb)
{
int hlen;

if (unlikely(!OVS_CB(skb)->tun_key)) {
ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
kfree_skb(skb);
return 0;
}

hlen = gre64_hdr_len(OVS_CB(skb)->tun_key);
return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre64_build_header);
}

const struct vport_ops ovs_gre64_vport_ops = {
Expand All @@ -404,6 +429,6 @@ const struct vport_ops ovs_gre64_vport_ops = {
.exit = gre_exit,
.create = gre64_create,
.destroy = gre64_tnl_destroy,
.get_name = ovs_tnl_get_name,
.send = ovs_tnl_send,
.get_name = gre_get_name,
.send = gre64_tnl_send,
};
Loading

0 comments on commit c405d28

Please sign in to comment.