When controller send OFPT_PACKET_OUT message, with its input port set to a patch port, and the packet handling requires recirculation, the post recirculation flow is never set up since the xlate layer rejects the up call triggered by such packet, on the bases those up calls don't have valid datapath input port. Patch ports don't have corresponding datapath ports.
A reasonable solution is by injecting the packet into datapath using LOCAL port's datapath port id. This patch implements such solution. It works against a test case provided by Simon. Reported-by: Simon Horman <ho...@verge.net.au> Signed-off-by: Andy Zhou <az...@nicira.com> --- ofproto/ofproto-dpif.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4cebd77..afc2f21 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -195,6 +195,8 @@ static void vsp_add(struct ofport_dpif *, ofp_port_t realdev_ofp_port, int vid); static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *, ofp_port_t); +static odp_port_t packet_out_odp_port(const struct ofproto_dpif *, + ofp_port_t); static ofp_port_t odp_port_to_ofp_port(const struct ofproto_dpif *, odp_port_t); @@ -3145,7 +3147,7 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, 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, in_port); execute.needs_help = (xout.slow & SLOW_ACTION) != 0; error = dpif_execute(ofproto->backer->dpif, &execute); @@ -4745,6 +4747,21 @@ 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 as LOCAL port, that is safe to send + * into the datapatch. */ +static odp_port_t +packet_out_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port) +{ + const struct ofport_dpif *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