X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=aa4c1097e79da09fd8f857e5d072411336fb01d2;hb=c5cf10598f8c9f4428291e9df3ecd72a05fb1ccf;hp=6dfe69d9e56f9edc61573be17eb03996552a79f1;hpb=beb1c69a3a661dbc0232aeb9831c14788f84eb24;p=sliver-openvswitch.git diff --git a/datapath/datapath.c b/datapath/datapath.c index 6dfe69d9e..aa4c1097e 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -135,7 +135,6 @@ int lockdep_ovsl_is_held(void) } #endif -static struct vport *new_vport(const struct vport_parms *); static int queue_gso_packets(struct datapath *dp, struct sk_buff *, const struct dp_upcall_info *); static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, @@ -240,33 +239,25 @@ void ovs_dp_detach_port(struct vport *p) ovs_vport_del(p); } -/* Must be called with rcu_read_lock. */ -void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) +void ovs_dp_process_packet_with_key(struct sk_buff *skb, + struct sw_flow_key *pkt_key) { + const struct vport *p = OVS_CB(skb)->input_vport; struct datapath *dp = p->dp; struct sw_flow *flow; struct dp_stats_percpu *stats; - struct sw_flow_key key; u64 *stats_counter; u32 n_mask_hit; - int error; stats = this_cpu_ptr(dp->stats_percpu); - /* Extract flow from 'skb' into 'key'. */ - error = ovs_flow_extract(skb, p->port_no, &key); - if (unlikely(error)) { - kfree_skb(skb); - return; - } - /* Look up flow. */ - flow = ovs_flow_tbl_lookup_stats(&dp->table, &key, &n_mask_hit); + flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, &n_mask_hit); if (unlikely(!flow)) { struct dp_upcall_info upcall; upcall.cmd = OVS_PACKET_CMD_MISS; - upcall.key = &key; + upcall.key = pkt_key; upcall.userdata = NULL; upcall.portid = ovs_vport_find_upcall_portid(p, skb); ovs_dp_upcall(dp, skb, &upcall); @@ -275,10 +266,10 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) goto out; } + OVS_CB(skb)->pkt_key = pkt_key; OVS_CB(skb)->flow = flow; - OVS_CB(skb)->pkt_key = &key; - ovs_flow_stats_update(OVS_CB(skb)->flow, key.tp.flags, skb); + ovs_flow_stats_update(OVS_CB(skb)->flow, pkt_key->tp.flags, skb); ovs_execute_actions(dp, skb); stats_counter = &stats->n_hit; @@ -290,6 +281,24 @@ out: u64_stats_update_end(&stats->sync); } +/* Must be called with rcu_read_lock. */ +void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) +{ + int error; + struct sw_flow_key key; + + OVS_CB(skb)->input_vport = p; + + /* Extract flow from 'skb' into 'key'. */ + error = ovs_flow_extract(skb, p->port_no, &key); + if (unlikely(error)) { + kfree_skb(skb); + return; + } + + ovs_dp_process_packet_with_key(skb, &key); +} + int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, const struct dp_upcall_info *upcall_info) { @@ -516,6 +525,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) struct sw_flow *flow; struct datapath *dp; struct ethhdr *eth; + struct vport *input_vport; int len; int err; @@ -579,6 +589,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) if (!dp) goto err_unlock; + input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port); + if (!input_vport) + input_vport = ovs_vport_rcu(dp, OVSP_LOCAL); + + if (!input_vport) + goto err_unlock; + + OVS_CB(packet)->input_vport = input_vport; + local_bh_disable(); err = ovs_execute_actions(dp, packet); local_bh_enable();