When controller sends OFPT_PACKET_OUT message with the in_port set to a patch port or as CONTROLLER, and the message execution requires recirculation, those packets will be dropped in the datapath. This is because the post recirculation flow will not be set up by Xlate layer that rejects up call without a valid datapath input port.
This patch implements a reasonable solution by injecting packets' in_port does not have a valid datapath port using LOCAL port's datapath port id. Reported-by: Simon Horman <ho...@verge.net.au> Signed-off-by: Andy Zhou <az...@nicira.com> -- v1 -> v2: Also handles CONTROLLER as input port --- ofproto/ofproto-dpif.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4cebd77..d1b1405 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -193,6 +193,7 @@ struct vlan_splinter { static void vsp_remove(struct ofport_dpif *); static void vsp_add(struct ofport_dpif *, ofp_port_t realdev_ofp_port, int vid); +static odp_port_t packet_out_odp_port(const struct ofproto_dpif *, ofp_port_t); static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *, ofp_port_t); @@ -3117,7 +3118,6 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, struct dpif_flow_stats stats; struct xlate_out xout; struct xlate_in xin; - ofp_port_t in_port; struct dpif_execute execute; int error; @@ -3135,17 +3135,14 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, xin.resubmit_stats = &stats; xlate_actions(&xin, &xout); - in_port = flow->in_port.ofp_port; - if (in_port == OFPP_NONE) { - in_port = OFPP_LOCAL; - } execute.actions = ofpbuf_data(&xout.odp_actions); execute.actions_len = ofpbuf_size(&xout.odp_actions); execute.packet = packet; execute.md.tunnel = flow->tunnel; execute.md.skb_priority = flow->skb_priority; execute.md.pkt_mark = flow->pkt_mark; - execute.md.in_port.odp_port = ofp_port_to_odp_port(ofproto, in_port); + execute.md.in_port.odp_port = packet_out_odp_port(ofproto, + flow->in_port.ofp_port); execute.needs_help = (xout.slow & SLOW_ACTION) != 0; error = dpif_execute(ofproto->backer->dpif, &execute); @@ -4745,6 +4742,29 @@ ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port) return ofport ? ofport->odp_port : ODPP_NONE; } +/* Converts ofp port to odp port, similar to ofp_port_to_odp_port. + * This function treats patch ports and CONTROLLER port as LOCAL port. + * + * In case the packet out execution requires recirculation, the post + * recirculation upcall with a valid datapath in_port will not be rejected + * by the xlate layer. */ +static odp_port_t +packet_out_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port) +{ + const struct ofport_dpif *ofport; + + if ((ofp_port == OFPP_NONE) || (ofp_port == OFPP_CONTROLLER)) { + ofp_port = OFPP_LOCAL; + } + + ofport = get_ofp_port(ofproto, ofp_port); + if (ofport && netdev_vport_is_patch(ofport->up.netdev)) { + ofport = get_ofp_port(ofproto, OFPP_LOCAL); + } + + return ofport ? ofport->odp_port : ODPP_NONE; +} + struct ofport_dpif * odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port) { -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev