diff --git a/datapath/actions.c b/datapath/actions.c index 603c7cb5f..72fdcf9f5 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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: @@ -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. */ diff --git a/datapath/datapath.c b/datapath/datapath.c index a4d6473e6..351a07563 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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 */ diff --git a/datapath/datapath.h b/datapath/datapath.h index a847bd992..fcd8e861e 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -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) diff --git a/datapath/flow.c b/datapath/flow.c index 2a839ffac..f1bb95d7f 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -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; diff --git a/datapath/flow.h b/datapath/flow.h index 201869128..0ecf78bd4 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -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 { diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 803a94cb5..0048a6e90 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -1160,13 +1160,14 @@ out: 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); @@ -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; } @@ -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); @@ -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; @@ -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; diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c index 5d5090c89..f30f0906d 100644 --- a/datapath/vport-gre.c +++ b/datapath/vport-gre.c @@ -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)); @@ -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; @@ -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; } @@ -139,6 +140,7 @@ 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; @@ -146,12 +148,10 @@ static int __send(struct vport *vport, struct sk_buff *skb, 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); @@ -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: @@ -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); } @@ -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)); } diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c index 86c7c5b91..8f96815ef 100644 --- a/datapath/vport-lisp.c +++ b/datapath/vport-lisp.c @@ -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)); @@ -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; @@ -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); @@ -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: @@ -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; @@ -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) && @@ -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); @@ -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; diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c index cc9477dd1..41c1756b0 100644 --- a/datapath/vport-vxlan.c +++ b/datapath/vport-vxlan.c @@ -60,7 +60,7 @@ static inline struct vxlan_port *vxlan_vport(const struct vport *vport) /* Called with rcu_read_lock and BH disabled. */ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni) { - struct ovs_key_ipv4_tunnel tun_key; + struct ovs_tunnel_info tun_info; struct vport *vport = vs->data; struct iphdr *iph; __be64 key; @@ -68,9 +68,9 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni) /* Save outer tunnel values */ iph = ip_hdr(skb); key = cpu_to_be64(ntohl(vx_vni) >> 8); - ovs_flow_tun_key_init(&tun_key, iph, key, TUNNEL_KEY); + ovs_flow_tun_info_init(&tun_info, iph, key, TUNNEL_KEY); - ovs_vport_receive(vport, skb, &tun_key); + ovs_vport_receive(vport, skb, &tun_info); } static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb) @@ -139,6 +139,7 @@ error: static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) { + struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel; struct net *net = ovs_dp_get_net(vport->dp); struct vxlan_port *vxlan_port = vxlan_vport(vport); __be16 dst_port = inet_sport(vxlan_port->vs->sock->sk); @@ -150,38 +151,34 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) int port_max; int err; - if (unlikely(!OVS_CB(skb)->tun_key)) { + if (unlikely(!OVS_CB(skb)->tun_info)) { err = -EINVAL; goto error; } /* 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); goto error; } - 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; inet_get_local_port_range(net, &port_min, &port_max); src_port = vxlan_src_port(port_min, port_max, skb); err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, - saddr, OVS_CB(skb)->tun_key->ipv4_dst, - OVS_CB(skb)->tun_key->ipv4_tos, - OVS_CB(skb)->tun_key->ipv4_ttl, df, + saddr, tun_key->ipv4_dst, + tun_key->ipv4_tos, + tun_key->ipv4_ttl, df, src_port, dst_port, - htonl(be64_to_cpu(OVS_CB(skb)->tun_key->tun_id) << 8)); + htonl(be64_to_cpu(tun_key->tun_id) << 8)); if (err < 0) ip_rt_put(rt); error: diff --git a/datapath/vport.c b/datapath/vport.c index 0dcecd048..5fce377fe 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -460,14 +460,14 @@ u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb) * * @vport: vport that received the packet * @skb: skb that was received - * @tun_key: tunnel (if any) that carried packet + * @tun_info: tunnel (if any) that carried packet * * Must be called with rcu_read_lock. The packet cannot be shared and * skb->data should point to the Ethernet header. The caller must have already * called compute_ip_summed() to initialize the checksumming fields. */ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, - struct ovs_key_ipv4_tunnel *tun_key) + struct ovs_tunnel_info *tun_info) { struct pcpu_sw_netstats *stats; @@ -477,7 +477,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); - OVS_CB(skb)->tun_key = tun_key; + OVS_CB(skb)->tun_info = tun_info; ovs_dp_process_received_packet(vport, skb); } diff --git a/datapath/vport.h b/datapath/vport.h index cfaea09bf..c02daf5bb 100644 --- a/datapath/vport.h +++ b/datapath/vport.h @@ -211,7 +211,7 @@ static inline struct vport *vport_from_priv(void *priv) } void ovs_vport_receive(struct vport *, struct sk_buff *, - struct ovs_key_ipv4_tunnel *); + struct ovs_tunnel_info *); /* List of statically compiled vport implementations. Don't forget to also * add yours to the list at the top of vport.c. */ diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index d7f85ffa8..33423add1 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -320,7 +320,7 @@ enum ovs_key_attr { OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */ #ifdef __KERNEL__ /* Only used within kernel data path. */ - OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */ + OVS_KEY_ATTR_TUNNEL_INFO, /* struct ovs_tunnel_info */ #endif /* Experimental */