Skip to content

Commit

Permalink
datapath: Wrap struct ovs_key_ipv4_tunnel in a new structure.
Browse files Browse the repository at this point in the history
Currently, the flow information that is matched for tunnels and
the tunnel data passed around with packets is the same. However,
as additional information is added this is not necessarily desirable,
as in the case of pointers.

This adds a new structure for tunnel metadata which currently contains
only the existing struct. This change is purely internal to the kernel
since the current OVS_KEY_ATTR_IPV4_TUNNEL is simply a compressed version
of OVS_KEY_ATTR_TUNNEL that is translated at flow setup.

Signed-off-by: Jesse Gross <[email protected]>
Acked-by: Thomas Graf <[email protected]>
Acked-by: Pravin B Shelar <[email protected]>
  • Loading branch information
jessegross committed Jun 20, 2014
1 parent 9cef26a commit f0cd669
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 81 deletions.
6 changes: 3 additions & 3 deletions datapath/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,8 @@ static int execute_set_action(struct sk_buff *skb,
skb->mark = nla_get_u32(nested_attr);
break;

case OVS_KEY_ATTR_IPV4_TUNNEL:
OVS_CB(skb)->tun_key = nla_data(nested_attr);
case OVS_KEY_ATTR_TUNNEL_INFO:
OVS_CB(skb)->tun_info = nla_data(nested_attr);
break;

case OVS_KEY_ATTR_ETHERNET:
Expand Down Expand Up @@ -701,7 +701,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb, bool recirc)
goto out_loop;
}

OVS_CB(skb)->tun_key = NULL;
OVS_CB(skb)->tun_info = NULL;
error = do_execute_actions(dp, skb, acts->actions, acts->actions_len);

/* Check whether sub-actions looped too much. */
Expand Down
2 changes: 1 addition & 1 deletion datapath/datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ static size_t key_attr_size(void)
{
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
* updating this function. */
BUILD_BUG_ON(OVS_KEY_ATTR_IPV4_TUNNEL != 21);
BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 21);

return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
Expand Down
2 changes: 1 addition & 1 deletion datapath/datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct datapath {
struct ovs_skb_cb {
struct sw_flow *flow;
struct sw_flow_key *pkt_key;
struct ovs_key_ipv4_tunnel *tun_key;
struct ovs_tunnel_info *tun_info;
struct vport *input_vport;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
Expand Down
11 changes: 7 additions & 4 deletions datapath/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,12 +451,15 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
int error;
struct ethhdr *eth;

key->phy.priority = skb->priority;
if (OVS_CB(skb)->tun_key)
memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
else
if (OVS_CB(skb)->tun_info) {
struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info;
memcpy(&key->tun_key, &tun_info->tunnel,
sizeof(key->tun_key));
} else {
memset(&key->tun_key, 0, sizeof(key->tun_key));
}

key->phy.priority = skb->priority;
key->phy.in_port = in_port;
key->phy.skb_mark = skb->mark;
key->ovs_flow_hash = 0;
Expand Down
22 changes: 13 additions & 9 deletions datapath/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,24 @@ struct ovs_key_ipv4_tunnel {
u8 ipv4_ttl;
} __packed __aligned(4); /* Minimize padding. */

static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
struct ovs_tunnel_info {
struct ovs_key_ipv4_tunnel tunnel;
};

static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
const struct iphdr *iph, __be64 tun_id,
__be16 tun_flags)
{
tun_key->tun_id = tun_id;
tun_key->ipv4_src = iph->saddr;
tun_key->ipv4_dst = iph->daddr;
tun_key->ipv4_tos = iph->tos;
tun_key->ipv4_ttl = iph->ttl;
tun_key->tun_flags = tun_flags;
tun_info->tunnel.tun_id = tun_id;
tun_info->tunnel.ipv4_src = iph->saddr;
tun_info->tunnel.ipv4_dst = iph->daddr;
tun_info->tunnel.ipv4_tos = iph->tos;
tun_info->tunnel.ipv4_ttl = iph->ttl;
tun_info->tunnel.tun_flags = tun_flags;

/* clear struct padding. */
memset((unsigned char *) tun_key + OVS_TUNNEL_KEY_SIZE, 0,
sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
memset((unsigned char *) &tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
}

struct sw_flow_key {
Expand Down
38 changes: 31 additions & 7 deletions datapath/flow_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1160,13 +1160,14 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
}

static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len)
static struct nlattr *__add_action(struct sw_flow_actions **sfa, int attrtype,
void *data, int len)
{
struct nlattr *a;

a = reserve_sfa_size(sfa, nla_attr_size(len));
if (IS_ERR(a))
return PTR_ERR(a);
return a;

a->nla_type = attrtype;
a->nla_len = nla_attr_size(len);
Expand All @@ -1175,6 +1176,18 @@ static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, in
memcpy(nla_data(a), data, len);
memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));

return a;
}

static int add_action(struct sw_flow_actions **sfa, int attrtype,
void *data, int len)
{
struct nlattr *a;

a = __add_action(sfa, attrtype, data, len);
if (IS_ERR(a))
return PTR_ERR(a);

return 0;
}

Expand Down Expand Up @@ -1280,6 +1293,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
{
struct sw_flow_match match;
struct sw_flow_key key;
struct ovs_tunnel_info *tun_info;
struct nlattr *a;
int err, start;

ovs_match_init(&match, &key, NULL);
Expand All @@ -1291,8 +1306,14 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
if (start < 0)
return start;

err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &match.key->tun_key,
sizeof(match.key->tun_key));
a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
sizeof(*tun_info));
if (IS_ERR(a))
return PTR_ERR(a);

tun_info = nla_data(a);
tun_info->tunnel = key.tun_key;

add_nested_action_end(*sfa, start);

return err;
Expand Down Expand Up @@ -1575,17 +1596,20 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
int err;

switch (key_type) {
case OVS_KEY_ATTR_IPV4_TUNNEL:
case OVS_KEY_ATTR_TUNNEL_INFO: {
struct ovs_tunnel_info *tun_info = nla_data(ovs_key);

start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
if (!start)
return -EMSGSIZE;

err = ipv4_tun_to_nlattr(skb, nla_data(ovs_key),
nla_data(ovs_key));
err = ipv4_tun_to_nlattr(skb, &tun_info->tunnel,
&tun_info->tunnel);
if (err)
return err;
nla_nest_end(skb, start);
break;
}
default:
if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
return -EMSGSIZE;
Expand Down
38 changes: 18 additions & 20 deletions datapath/vport-gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static struct sk_buff *__build_header(struct sk_buff *skb,
int tunnel_hlen,
__be32 seq, __be16 gre64_flag)
{
const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
const struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
struct tnl_ptk_info tpi;

skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
Expand Down Expand Up @@ -96,7 +96,7 @@ static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
static int gre_rcv(struct sk_buff *skb,
const struct tnl_ptk_info *tpi)
{
struct ovs_key_ipv4_tunnel tun_key;
struct ovs_tunnel_info tun_info;
struct ovs_net *ovs_net;
struct vport *vport;
__be64 key;
Expand All @@ -110,9 +110,10 @@ static int gre_rcv(struct sk_buff *skb,
return PACKET_REJECT;

key = key_to_tunnel_id(tpi->key, tpi->seq);
ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key, filter_tnl_flags(tpi->flags));
ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), key,
filter_tnl_flags(tpi->flags));

ovs_vport_receive(vport, skb, &tun_key);
ovs_vport_receive(vport, skb, &tun_info);
return PACKET_RCVD;
}

Expand All @@ -139,19 +140,18 @@ static int __send(struct vport *vport, struct sk_buff *skb,
int tunnel_hlen,
__be32 seq, __be16 gre64_flag)
{
struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
struct rtable *rt;
int min_headroom;
__be16 df;
__be32 saddr;
int err;

/* Route lookup */
saddr = OVS_CB(skb)->tun_key->ipv4_src;
saddr = tun_key->ipv4_src;
rt = find_route(ovs_dp_get_net(vport->dp),
&saddr,
OVS_CB(skb)->tun_key->ipv4_dst,
IPPROTO_GRE,
OVS_CB(skb)->tun_key->ipv4_tos,
&saddr, tun_key->ipv4_dst,
IPPROTO_GRE, tun_key->ipv4_tos,
skb->mark);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
Expand Down Expand Up @@ -189,15 +189,13 @@ static int __send(struct vport *vport, struct sk_buff *skb,
goto err_free_rt;
}

df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
htons(IP_DF) : 0;

df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
skb->local_df = 1;

return iptunnel_xmit(rt, skb, saddr,
OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,
OVS_CB(skb)->tun_key->ipv4_tos,
OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
tun_key->ipv4_dst, IPPROTO_GRE,
tun_key->ipv4_tos,
tun_key->ipv4_ttl, df, false);
err_free_rt:
ip_rt_put(rt);
error:
Expand Down Expand Up @@ -286,10 +284,10 @@ static int gre_send(struct vport *vport, struct sk_buff *skb)
{
int hlen;

if (unlikely(!OVS_CB(skb)->tun_key))
if (unlikely(!OVS_CB(skb)->tun_info))
return -EINVAL;

hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_key->tun_flags);
hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_info->tunnel.tun_flags);

return __send(vport, skb, hlen, 0, 0);
}
Expand Down Expand Up @@ -360,13 +358,13 @@ static int gre64_send(struct vport *vport, struct sk_buff *skb)
GRE_HEADER_SECTION; /* GRE SEQ */
__be32 seq;

if (unlikely(!OVS_CB(skb)->tun_key))
if (unlikely(!OVS_CB(skb)->tun_info))
return -EINVAL;

if (OVS_CB(skb)->tun_key->tun_flags & TUNNEL_CSUM)
if (OVS_CB(skb)->tun_info->tunnel.tun_flags & TUNNEL_CSUM)
hlen += GRE_HEADER_SECTION;

seq = be64_get_high32(OVS_CB(skb)->tun_key->tun_id);
seq = be64_get_high32(OVS_CB(skb)->tun_info->tunnel.tun_id);
return __send(vport, skb, hlen, seq, (TUNNEL_KEY|TUNNEL_SEQ));
}

Expand Down
28 changes: 13 additions & 15 deletions datapath/vport-lisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static void lisp_build_header(const struct vport *vport,
struct lisp_port *lisp_port = lisp_vport(vport);
struct udphdr *udph = udp_hdr(skb);
struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
const struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;

udph->dest = lisp_port->dst_port;
udph->source = htons(get_src_port(net, skb));
Expand Down Expand Up @@ -224,7 +224,7 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
struct lisp_port *lisp_port;
struct lisphdr *lisph;
struct iphdr *iph, *inner_iph;
struct ovs_key_ipv4_tunnel tun_key;
struct ovs_tunnel_info tun_info;
__be64 key;
struct ethhdr *ethh;
__be16 protocol;
Expand All @@ -245,7 +245,7 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)

/* Save outer tunnel values */
iph = ip_hdr(skb);
ovs_flow_tun_key_init(&tun_key, iph, key, TUNNEL_KEY);
ovs_flow_tun_info_init(&tun_info, iph, key, TUNNEL_KEY);

/* Drop non-IP inner packets */
inner_iph = (struct iphdr *)(lisph + 1);
Expand All @@ -270,7 +270,7 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)

ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);

ovs_vport_receive(vport_from_priv(lisp_port), skb, &tun_key);
ovs_vport_receive(vport_from_priv(lisp_port), skb, &tun_info);
goto out;

error:
Expand Down Expand Up @@ -425,6 +425,7 @@ static int handle_offloads(struct sk_buff *skb)

static int lisp_send(struct vport *vport, struct sk_buff *skb)
{
struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
int network_offset = skb_network_offset(skb);
struct rtable *rt;
int min_headroom;
Expand All @@ -433,7 +434,7 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
int sent_len;
int err;

if (unlikely(!OVS_CB(skb)->tun_key))
if (unlikely(!OVS_CB(skb)->tun_info))
return -EINVAL;

if (skb->protocol != htons(ETH_P_IP) &&
Expand All @@ -443,12 +444,10 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
}

/* Route lookup */
saddr = OVS_CB(skb)->tun_key->ipv4_src;
saddr = tun_key->ipv4_src;
rt = find_route(ovs_dp_get_net(vport->dp),
&saddr,
OVS_CB(skb)->tun_key->ipv4_dst,
IPPROTO_UDP,
OVS_CB(skb)->tun_key->ipv4_tos,
&saddr, tun_key->ipv4_dst,
IPPROTO_UDP, tun_key->ipv4_tos,
skb->mark);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
Expand Down Expand Up @@ -488,12 +487,11 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)

skb->local_df = 1;

df = OVS_CB(skb)->tun_key->tun_flags &
TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
sent_len = iptunnel_xmit(rt, skb,
saddr, OVS_CB(skb)->tun_key->ipv4_dst,
IPPROTO_UDP, OVS_CB(skb)->tun_key->ipv4_tos,
OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
saddr, tun_key->ipv4_dst,
IPPROTO_UDP, tun_key->ipv4_tos,
tun_key->ipv4_ttl, df, false);

return sent_len > 0 ? sent_len + network_offset : sent_len;

Expand Down
Loading

0 comments on commit f0cd669

Please sign in to comment.