return (masks[type] & (1u << reason)) != 0;
}
-/* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
- * packet rather than to send the packet to the controller.
- *
- * This function returns false to indicate the packet should be dropped if
- * the controller action was the result of the default table-miss behaviour
- * and the controller is using OpenFlow1.3+.
- *
- * Otherwise true is returned to indicate the packet should be forwarded to
- * the controller */
-static bool
-ofconn_wants_packet_in_on_miss(struct ofconn *ofconn,
- const struct ofproto_packet_in *pin)
-{
- if (pin->miss_type == OFPROTO_PACKET_IN_MISS_WITHOUT_FLOW) {
- enum ofputil_protocol protocol = ofconn_get_protocol(ofconn);
-
- if (protocol != OFPUTIL_P_NONE
- && ofputil_protocol_to_ofp_version(protocol) >= OFP13_VERSION
- && (ofproto_table_get_miss_config(ofconn->connmgr->ofproto,
- pin->up.table_id)
- == OFPUTIL_TABLE_MISS_DEFAULT)) {
- return false;
- }
- }
- return true;
-}
-
/* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
* packet rather than to send the packet to the controller.
*
\f
/* Sending asynchronous messages. */
-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'. For messages caused by a controller
* OFPT_PORT_MOD, specify 'source' as the controller connection that sent the
}
}
-/* 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)
-{
- enum ofputil_protocol protocol = ofconn_get_protocol(ofconn);
-
- if (pin->miss_type == OFPROTO_PACKET_IN_MISS_FLOW
- && pin->up.reason == OFPR_ACTION
- && protocol != OFPUTIL_P_NONE
- && ofputil_protocol_to_ofp_version(protocol) >= OFP13_VERSION) {
- return OFPR_NO_MATCH;
- }
-
- switch (pin->up.reason) {
- case OFPR_ACTION_SET:
- case OFPR_GROUP:
- case OFPR_PACKET_OUT:
- if (!(protocol & OFPUTIL_P_OF14_UP)) {
- /* Only supported in OF1.4+ */
- return OFPR_ACTION;
- }
- /* Fall through. */
- case OFPR_NO_MATCH:
- case OFPR_ACTION:
- case OFPR_INVALID_TTL:
- case OFPR_N_REASONS:
- default:
- return pin->up.reason;
- }
-}
-
/* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as
* necessary according to their individual configurations.
*
struct ofconn *ofconn;
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
- enum ofp_packet_in_reason reason = wire_reason(ofconn, pin);
-
- if (ofconn_wants_packet_in_on_miss(ofconn, pin)
- && ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, reason)
- && ofconn->controller_id == pin->controller_id) {
- schedule_packet_in(ofconn, *pin, reason);
+ enum ofputil_protocol protocol = ofconn_get_protocol(ofconn);
+ if (protocol == OFPUTIL_P_NONE || !rconn_is_connected(ofconn->rconn)
+ || ofconn->controller_id != pin->controller_id
+ || !ofconn_receives_async_msg(ofconn, OAM_PACKET_IN,
+ pin->up.reason)) {
+ continue;
}
+
+ struct ofpbuf *msg = ofputil_encode_packet_in(
+ &pin->up, protocol, ofconn->packet_in_format,
+ pin->max_len >= 0 ? pin->max_len : ofconn->miss_send_len,
+ ofconn->pktbuf);
+
+ struct ovs_list txq;
+ bool is_miss = (pin->up.reason == OFPR_NO_MATCH ||
+ pin->up.reason == OFPR_EXPLICIT_MISS ||
+ pin->up.reason == OFPR_IMPLICIT_MISS);
+ pinsched_send(ofconn->schedulers[is_miss],
+ pin->up.flow_metadata.flow.in_port.ofp_port, msg, &txq);
+ do_send_packet_ins(ofconn, &txq);
}
}
}
}
}
-
-/* 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,
- enum ofp_packet_in_reason wire_reason)
-{
- uint16_t controller_max_len;
- struct ovs_list txq;
-
- 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 {
- controller_max_len = ofconn->miss_send_len;
- }
-
- /* Get OpenFlow buffer_id.
- * For OpenFlow 1.2+, OFPCML_NO_BUFFER (== UINT16_MAX) specifies
- * unbuffered. This behaviour doesn't violate prior versions, too. */
- if (controller_max_len == UINT16_MAX) {
- pin.up.buffer_id = UINT32_MAX;
- } else if (!ofconn->pktbuf) {
- pin.up.buffer_id = UINT32_MAX;
- } else {
- pin.up.buffer_id = pktbuf_save(ofconn->pktbuf,
- pin.up.packet, pin.up.packet_len,
- pin.up.flow_metadata.flow.in_port.ofp_port);
- }
-
- /* Figure out how much of the packet to send.
- * If not buffered, send the entire packet. Otherwise, depending on
- * the reason of packet-in, send what requested by the controller. */
- if (pin.up.buffer_id != UINT32_MAX
- && controller_max_len < pin.up.packet_len) {
- pin.up.packet_len = controller_max_len;
- }
-
- /* Make OFPT_PACKET_IN and hand over to packet scheduler. */
- pinsched_send(ofconn->schedulers[pin.up.reason == OFPR_NO_MATCH ? 0 : 1],
- pin.up.flow_metadata.flow.in_port.ofp_port,
- ofputil_encode_packet_in(&pin.up,
- ofconn_get_protocol(ofconn),
- ofconn->packet_in_format),
- &txq);
- do_send_packet_ins(ofconn, &txq);
-}
\f
/* Fail-open settings. */