break;
case OVS_KEY_ATTR_TUNNEL_INFO:
- OVS_CB(skb)->tun_info = nla_data(nested_attr);
+ OVS_CB(skb)->egress_tun_info = nla_data(nested_attr);
break;
case OVS_KEY_ATTR_ETHERNET:
}
static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
- const struct nlattr *a)
+ const struct nlattr *a)
{
struct sw_flow_key recirc_key;
int err;
return err;
}
-
- ovs_dp_process_packet_with_key(skb, &recirc_key, true);
+ ovs_dp_process_packet(skb, true);
return 0;
}
goto out_loop;
}
- OVS_CB(skb)->tun_info = NULL;
error = do_execute_actions(dp, skb, acts->actions, acts->actions_len);
/* Check whether sub-actions looped too much. */
ovs_vport_del(p);
}
-void ovs_dp_process_packet_with_key(struct sk_buff *skb,
- struct sw_flow_key *pkt_key,
- bool recirc)
+/* Must be called with rcu_read_lock. */
+void ovs_dp_process_packet(struct sk_buff *skb, bool recirc)
{
const struct vport *p = OVS_CB(skb)->input_vport;
+ struct sw_flow_key *pkt_key = OVS_CB(skb)->pkt_key;
struct datapath *dp = p->dp;
struct sw_flow *flow;
struct dp_stats_percpu *stats;
u32 n_mask_hit;
stats = this_cpu_ptr(dp->stats_percpu);
- OVS_CB(skb)->pkt_key = pkt_key;
/* Look up flow. */
flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, skb_get_hash(skb),
u64_stats_update_end(&stats->sync);
}
-/* Must be called with rcu_read_lock. */
-void ovs_dp_process_received_packet(struct sk_buff *skb)
-{
- int error;
- struct sw_flow_key key;
-
- /* Extract flow from 'skb' into 'key'. */
- error = ovs_flow_key_extract(skb, &key);
- if (unlikely(error)) {
- kfree_skb(skb);
- return;
- }
-
- ovs_dp_process_packet_with_key(skb, &key, false);
-}
-
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
const struct dp_upcall_info *upcall_info)
{
OVS_CB(packet)->flow = flow;
OVS_CB(packet)->pkt_key = &flow->key;
+ OVS_CB(skb)->egress_tun_info = NULL;
packet->priority = flow->key.phy.priority;
packet->mark = flow->key.phy.skb_mark;
* struct ovs_skb_cb - OVS data in skb CB
* @flow: The flow associated with this packet. May be %NULL if no flow.
* @pkt_key: The flow information extracted from the packet. Must be nonnull.
- * @tun_info: Tunnel information about this packet. NULL if the packet
- * is not being tunneled.
+ * @egress_tun_info: Tunnel information about this packet on egress path.
+ * NULL if the packet is not being tunneled.
* @input_vport: The original vport packet came in on. This value is cached
* when a packet is received by OVS.
*/
struct ovs_skb_cb {
struct sw_flow *flow;
struct sw_flow_key *pkt_key;
- struct ovs_tunnel_info *tun_info;
+ struct ovs_tunnel_info *egress_tun_info;
struct vport *input_vport;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
extern struct genl_family dp_vport_genl_family;
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
-void ovs_dp_process_received_packet(struct sk_buff *);
-void ovs_dp_process_packet_with_key(struct sk_buff *,
- struct sw_flow_key *pkt_key, bool recirc);
+void ovs_dp_process_packet(struct sk_buff *, bool recirc);
void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *);
}
}
+ OVS_CB(skb)->pkt_key = key;
return 0;
}
-int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
+ struct sk_buff *skb,
+ struct sw_flow_key *key)
{
/* Extract metadata from packet. */
-
- if (OVS_CB(skb)->tun_info) {
- struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info;
-
+ if (tun_info) {
memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
BUILD_BUG_ON(((1 << (sizeof(tun_info->options_len) * 8)) - 1) >
void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies);
-int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
+ struct sk_buff *skb, struct sw_flow_key *key);
/* Extract key from packet coming from userspace. */
int ovs_flow_key_extract_userspace(const struct nlattr *attr,
struct sk_buff *skb,
struct geneve_port *geneve_port = geneve_vport(vport);
struct udphdr *udph = udp_hdr(skb);
struct genevehdr *geneveh = (struct genevehdr *)(udph + 1);
- const struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info;
+ const struct ovs_tunnel_info *tun_info = OVS_CB(skb)->egress_tun_info;
udph->dest = inet_sport(geneve_port->sock->sk);
udph->source = vxlan_src_port(1, USHRT_MAX, skb);
int sent_len;
int err;
- if (unlikely(!OVS_CB(skb)->tun_info))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
- tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
/* Route lookup */
saddr = tun_key->ipv4_src;
}
min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
- + GENEVE_BASE_HLEN + OVS_CB(skb)->tun_info->options_len
+ + GENEVE_BASE_HLEN
+ + OVS_CB(skb)->egress_tun_info->options_len
+ sizeof(struct iphdr)
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
skb_reset_inner_headers(skb);
- __skb_push(skb, GENEVE_BASE_HLEN + OVS_CB(skb)->tun_info->options_len);
+ __skb_push(skb, GENEVE_BASE_HLEN +
+ OVS_CB(skb)->egress_tun_info->options_len);
skb_reset_transport_header(skb);
geneve_build_header(vport, skb);
int tunnel_hlen,
__be32 seq, __be16 gre64_flag)
{
- const struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ const struct ovs_key_ipv4_tunnel *tun_key;
struct tnl_ptk_info tpi;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
if (IS_ERR(skb))
return NULL;
int tunnel_hlen,
__be32 seq, __be16 gre64_flag)
{
- struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ struct ovs_key_ipv4_tunnel *tun_key;
struct rtable *rt;
int min_headroom;
__be16 df;
int err;
/* Route lookup */
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
saddr = tun_key->ipv4_src;
rt = find_route(ovs_dp_get_net(vport->dp),
&saddr, tun_key->ipv4_dst,
{
int hlen;
- if (unlikely(!OVS_CB(skb)->tun_info))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
- hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_info->tunnel.tun_flags);
+ hlen = ip_gre_calc_hlen(OVS_CB(skb)->egress_tun_info->tunnel.tun_flags);
return __send(vport, skb, hlen, 0, 0);
}
GRE_HEADER_SECTION; /* GRE SEQ */
__be32 seq;
- if (unlikely(!OVS_CB(skb)->tun_info))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
- if (OVS_CB(skb)->tun_info->tunnel.tun_flags & TUNNEL_CSUM)
+ if (OVS_CB(skb)->egress_tun_info->tunnel.tun_flags & TUNNEL_CSUM)
hlen += GRE_HEADER_SECTION;
- seq = be64_get_high32(OVS_CB(skb)->tun_info->tunnel.tun_id);
+ seq = be64_get_high32(OVS_CB(skb)->egress_tun_info->tunnel.tun_id);
return __send(vport, skb, hlen, seq, (TUNNEL_KEY|TUNNEL_SEQ));
}
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_info->tunnel;
+ const struct ovs_key_ipv4_tunnel *tun_key;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
udph->dest = lisp_port->dst_port;
udph->source = htons(get_src_port(net, skb));
udph->check = 0;
int sent_len;
int err;
- if (unlikely(!OVS_CB(skb)->tun_info))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
- tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
if (skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_IPV6)) {
int port_max;
int err;
- if (unlikely(!OVS_CB(skb)->tun_info)) {
+ if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
err = -EINVAL;
goto error;
}
- tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
/* Route lookup */
saddr = tun_key->ipv4_src;
struct ovs_tunnel_info *tun_info)
{
struct pcpu_sw_netstats *stats;
+ struct sw_flow_key key;
+ int error;
stats = this_cpu_ptr(vport->percpu_stats);
u64_stats_update_begin(&stats->syncp);
u64_stats_update_end(&stats->syncp);
ovs_skb_init_inner_protocol(skb);
- OVS_CB(skb)->tun_info = tun_info;
OVS_CB(skb)->input_vport = vport;
- ovs_dp_process_received_packet(skb);
+ OVS_CB(skb)->egress_tun_info = NULL;
+ error = ovs_flow_key_extract(tun_info, skb, &key);
+ if (unlikely(error)) {
+ kfree_skb(skb);
+ return;
+ }
+
+ ovs_dp_process_packet(skb, false);
}
/**