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

Reply via email to