X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fconnmgr.c;h=d42ab4f93eccc99a14469f51ad18022a4e6e2b58;hb=cfa955b083c5617212a29a03423e063ff6cb350a;hp=f5bef59db59c9bdc80ce2229a75b7e6bacb1be30;hpb=ee1afdd55567263f8a10f9bff3e5ae6fc8e42fdb;p=sliver-openvswitch.git diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index f5bef59db..d42ab4f93 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -1435,7 +1435,8 @@ ofconn_send(const struct ofconn *ofconn, struct ofpbuf *msg, /* Sending asynchronous messages. */ -static void schedule_packet_in(struct ofconn *, struct ofproto_packet_in); +static void schedule_packet_in(struct ofconn *, struct ofproto_packet_in, + enum ofp_packet_in_reason wire_reason); /* Sends an OFPT_PORT_STATUS message with 'opp' and 'reason' to appropriate * controllers managed by 'mgr'. */ @@ -1482,6 +1483,25 @@ connmgr_send_flow_removed(struct connmgr *mgr, } } +/* Normally a send-to-controller action uses reason OFPR_ACTION. However, in + * OpenFlow 1.3 and later, packet_ins generated by a send-to-controller action + * in a "table-miss" flow (one with priority 0 and completely wildcarded) are + * sent as OFPR_NO_MATCH. This function returns the reason that should + * actually be sent on 'ofconn' for 'pin'. */ +static enum ofp_packet_in_reason +wire_reason(struct ofconn *ofconn, const struct ofproto_packet_in *pin) +{ + if (pin->generated_by_table_miss && pin->up.reason == OFPR_ACTION) { + enum ofputil_protocol protocol = ofconn_get_protocol(ofconn); + enum ofp_version version = ofputil_protocol_to_ofp_version(protocol); + + if (version >= OFP13_VERSION) { + return OFPR_NO_MATCH; + } + } + return pin->up.reason; +} + /* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as * necessary according to their individual configurations. * @@ -1493,9 +1513,11 @@ connmgr_send_packet_in(struct connmgr *mgr, struct ofconn *ofconn; LIST_FOR_EACH (ofconn, node, &mgr->all_conns) { - if (ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, pin->up.reason) + enum ofp_packet_in_reason reason = wire_reason(ofconn, pin); + + if (ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, reason) && ofconn->controller_id == pin->controller_id) { - schedule_packet_in(ofconn, *pin); + schedule_packet_in(ofconn, *pin, reason); } } } @@ -1513,13 +1535,15 @@ do_send_packet_in(struct ofpbuf *ofp_packet_in, void *ofconn_) /* Takes 'pin', composes an OpenFlow packet-in message from it, and passes it * to 'ofconn''s packet scheduler for sending. */ static void -schedule_packet_in(struct ofconn *ofconn, struct ofproto_packet_in pin) +schedule_packet_in(struct ofconn *ofconn, struct ofproto_packet_in pin, + enum ofp_packet_in_reason wire_reason) { struct connmgr *mgr = ofconn->connmgr; uint16_t controller_max_len; pin.up.total_len = pin.up.packet_len; + pin.up.reason = wire_reason; if (pin.up.reason == OFPR_ACTION) { controller_max_len = pin.send_len; /* max_len */ } else {