As per spec, make packet-in reason for OpenFlow1.3 table-miss flow entries no_match rather than action.
Signed-off-by: YAMAMOTO Takashi <yamam...@valinux.co.jp> --- OPENFLOW-1.1+ | 3 --- include/openflow/openflow-common.h | 5 ++++- lib/ofp-util.c | 3 +++ ofproto/connmgr.c | 33 ++++++++++++++++++++++++++++----- ofproto/ofproto-dpif-xlate.c | 12 +++++++++++- ofproto/ofproto-dpif.c | 8 ++++++++ ofproto/ofproto-dpif.h | 2 ++ 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+ index 4f30520..2405bb4 100644 --- a/OPENFLOW-1.1+ +++ b/OPENFLOW-1.1+ @@ -125,9 +125,6 @@ didn't compare the specs carefully yet.) - Change the default table-miss action (in the absense of table-miss entry) from packet_in to drop for OF1.3+. Decide what to do if a switch is configured to support multiple OF versions. - - Distinguish table-miss flow entry and make its packet_in reason - OFPR_NO_MATCH. (OFPR_TABLE_MISS for OF1.4) - Also, make it use the appropriate pin scheduler. [required for OF1.3+] * IPv6 extension header handling support. Fully implementing this diff --git a/include/openflow/openflow-common.h b/include/openflow/openflow-common.h index 45d03ef..7f73be2 100644 --- a/include/openflow/openflow-common.h +++ b/include/openflow/openflow-common.h @@ -275,7 +275,10 @@ enum ofp_packet_in_reason { OFPR_NO_MATCH, /* No matching flow. */ OFPR_ACTION, /* Action explicitly output to controller. */ OFPR_INVALID_TTL /* Packet has invalid TTL. */, - OFPR_N_REASONS + OFPR_N_REASONS, + + /* Action for OF1.3+ table-miss flow entry. Internal use only. */ + OFPR_ACTION_TABLE_MISS = 999, }; enum ofp_flow_mod_command { diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 2bf595a..2e08acc 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -2941,6 +2941,8 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin, size_t send_len = MIN(pin->send_len, pin->packet_len); struct ofpbuf *packet; + ovs_assert(pin->reason != OFPR_ACTION_TABLE_MISS); + /* Add OFPT_PACKET_IN. */ if (protocol == OFPUTIL_P_OF13_OXM || protocol == OFPUTIL_P_OF12_OXM) { struct ofp13_packet_in *opi; @@ -3037,6 +3039,7 @@ ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason, return "invalid_ttl"; case OFPR_N_REASONS: + case OFPR_ACTION_TABLE_MISS: default: snprintf(reasonbuf, bufsize, "%d", (int) reason); return reasonbuf; diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 8bb96f0..66e5909 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 ofputil_packet_in); +static void schedule_packet_in(struct ofconn *, struct ofputil_packet_in, + enum ofp_packet_in_reason reason); /* Sends an OFPT_PORT_STATUS message with 'opp' and 'reason' to appropriate * controllers managed by 'mgr'. */ @@ -1482,6 +1483,24 @@ connmgr_send_flow_removed(struct connmgr *mgr, } } +/* Turn OFPR_ACTION_TABLE_MISS, which is OVS-internal, into + * an appropritate on-wire reason. */ +static enum ofp_packet_in_reason +wire_reason(struct ofconn *ofconn, enum ofp_packet_in_reason reason) +{ + enum ofputil_protocol protocol; + + if (reason != OFPR_ACTION_TABLE_MISS) { + return reason; + } + protocol = ofconn_get_protocol(ofconn); + if (ofputil_protocol_to_ofp_version(protocol) < OFP13_VERSION) { + return OFPR_ACTION; + } else { + return OFPR_NO_MATCH; + } +} + /* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as * necessary according to their individual configurations. * @@ -1493,9 +1512,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->reason) + enum ofp_packet_in_reason reason = wire_reason(ofconn, pin->reason); + + 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,18 +1534,20 @@ 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 ofputil_packet_in pin) +schedule_packet_in(struct ofconn *ofconn, struct ofputil_packet_in pin, + enum ofp_packet_in_reason reason) { struct connmgr *mgr = ofconn->connmgr; uint16_t controller_max_len; pin.total_len = pin.packet_len; - if (pin.reason == OFPR_ACTION) { + if (pin.reason == OFPR_ACTION || pin.reason == OFPR_ACTION_TABLE_MISS) { controller_max_len = pin.send_len; /* max_len */ } else { controller_max_len = ofconn->miss_send_len; } + pin.reason = reason; /* Get OpenFlow buffer_id. * For OpenFlow 1.2+, OFPCML_NO_BUFFER (== UINT16_MAX) specifies diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 7371750..d22cc24 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2033,6 +2033,7 @@ xlate_output_action(struct xlate_ctx *ctx, ofp_port_t port, uint16_t max_len, bool may_packet_in) { ofp_port_t prev_nf_output_iface = ctx->xout->nf_output_iface; + enum ofp_packet_in_reason reason; ctx->xout->nf_output_iface = NF_OUT_DROP; @@ -2054,7 +2055,16 @@ xlate_output_action(struct xlate_ctx *ctx, flood_packets(ctx, true); break; case OFPP_CONTROLLER: - execute_controller_action(ctx, max_len, OFPR_ACTION, 0); + /* Remember if the match looks like an OpenFlow1.3 table-miss flow + * entry so that connmgr can later choose an appropriate packet-in + * reason for the OpenFlow version used for the connection. + * (no_match or action). */ + if (ctx->rule != NULL && rule_dpif_table_miss(ctx->rule)) { + reason = OFPR_ACTION_TABLE_MISS; + } else { + reason = OFPR_ACTION; + } + execute_controller_action(ctx, max_len, reason, 0); break; case OFPP_NONE: break; diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index e53bb25..837fef0 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4314,6 +4314,14 @@ rule_dpif_fail_open(const struct rule_dpif *rule) return rule->up.cr.priority == FAIL_OPEN_PRIORITY; } +bool +rule_dpif_table_miss(const struct rule_dpif *rule) +{ + const struct cls_rule *cls_rule = &rule->up.cr; + + return cls_rule->priority == 0 && cls_rule_is_catchall(cls_rule); +} + ovs_be64 rule_dpif_get_flow_cookie(const struct rule_dpif *rule) OVS_REQUIRES(rule->up.mutex) diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 51b1979..c4ffa89 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -75,6 +75,8 @@ void rule_dpif_credit_stats(struct rule_dpif *rule , bool rule_dpif_fail_open(const struct rule_dpif *rule); +bool rule_dpif_table_miss(const struct rule_dpif *rule); + struct rule_actions *rule_dpif_get_actions(const struct rule_dpif *); ovs_be64 rule_dpif_get_flow_cookie(const struct rule_dpif *rule); -- 1.8.3.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev