diff options
author | YAMAMOTO Takashi <yamamoto@valinux.co.jp> | 2013-10-22 21:50:23 -0700 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2013-10-23 08:37:41 -0700 |
commit | cfa955b083c5617212a29a03423e063ff6cb350a (patch) | |
tree | f72ae5ec1afb30a1cb73479e8ae270527bb9c5ea | |
parent | ee1afdd55567263f8a10f9bff3e5ae6fc8e42fdb (diff) |
connmgr: Fix packet-in reason for OpenFlow1.3 table-miss flow entries.
As per spec, make packet-in reason for OpenFlow1.3 table-miss flow
entries no_match rather than action.
Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: Ben Pfaff <blp@nicira.com>
-rw-r--r-- | OPENFLOW-1.1+ | 3 | ||||
-rw-r--r-- | ofproto/connmgr.c | 32 | ||||
-rw-r--r-- | ofproto/connmgr.h | 5 | ||||
-rw-r--r-- | ofproto/fail-open.c | 1 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-upcall.c | 1 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-xlate.c | 2 | ||||
-rw-r--r-- | ofproto/ofproto-dpif.c | 5 | ||||
-rw-r--r-- | ofproto/ofproto-dpif.h | 1 | ||||
-rw-r--r-- | ofproto/ofproto-provider.h | 12 |
9 files changed, 55 insertions, 7 deletions
diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+ index 22be72cd..bd6ced6b 100644 --- a/OPENFLOW-1.1+ +++ b/OPENFLOW-1.1+ @@ -130,9 +130,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/ofproto/connmgr.c b/ofproto/connmgr.c index f5bef59d..d42ab4f9 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 { diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h index e9ffbbc2..10caaf4e 100644 --- a/ofproto/connmgr.h +++ b/ofproto/connmgr.h @@ -68,6 +68,11 @@ struct ofproto_packet_in { struct list list_node; /* For queuing. */ uint16_t controller_id; /* Controller ID to send to. */ int send_len; /* Length that the action requested sending. */ + + /* True if the packet_in was generated directly by a table-miss flow, that + * is, a flow with priority 0 that wildcards all fields. (Our + * interpretation of "directly" is "not via groups".) */ + bool generated_by_table_miss; }; /* Basics. */ diff --git a/ofproto/fail-open.c b/ofproto/fail-open.c index b0caf8d6..bae9dcaf 100644 --- a/ofproto/fail-open.c +++ b/ofproto/fail-open.c @@ -130,6 +130,7 @@ send_bogus_packet_ins(struct fail_open *fo) pin.up.reason = OFPR_NO_MATCH; pin.up.fmd.in_port = OFPP_LOCAL; pin.send_len = b.size; + pin.generated_by_table_miss = false; connmgr_send_packet_in(fo->connmgr, &pin); ofpbuf_uninit(&b); diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 491f11e5..24a57296 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -849,6 +849,7 @@ handle_upcalls(struct udpif *udpif, struct list *upcalls) pin->up.cookie = OVS_BE64_MAX; flow_get_metadata(&miss->flow, &pin->up.fmd); pin->send_len = 0; /* Not used for flow table misses. */ + pin->generated_by_table_miss = false; ofproto_dpif_send_packet_in(miss->ofproto, pin); } } diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index ed9ca7cf..1eb09532 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -1856,6 +1856,8 @@ execute_controller_action(struct xlate_ctx *ctx, int len, pin->controller_id = controller_id; pin->send_len = len; + pin->generated_by_table_miss = (ctx->rule + && rule_dpif_is_table_miss(ctx->rule)); ofproto_dpif_send_packet_in(ctx->xbridge->ofproto, pin); ofpbuf_delete(packet); } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 67c21f54..be7f807d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4308,6 +4308,11 @@ rule_dpif_is_fail_open(const struct rule_dpif *rule) { return is_fail_open_rule(&rule->up); } + +bool +rule_dpif_is_table_miss(const struct rule_dpif *rule) +{ + return rule_is_table_miss(&rule->up); } ovs_be64 diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index ab5dfbbd..c93d37c2 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -75,6 +75,7 @@ void rule_dpif_credit_stats(struct rule_dpif *rule , const struct dpif_flow_stats *); bool rule_dpif_is_fail_open(const struct rule_dpif *); +bool rule_dpif_is_table_miss(const struct rule_dpif *); struct rule_actions *rule_dpif_get_actions(const struct rule_dpif *); diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index de566e3b..07bb266f 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -398,6 +398,18 @@ struct rule_actions *rule_get_actions(const struct rule *rule) struct rule_actions *rule_get_actions__(const struct rule *rule) OVS_REQUIRES(rule->mutex); +/* Returns true if 'rule' is an OpenFlow 1.3 "table-miss" rule, false + * otherwise. + * + * ("Table-miss" rules are special because a packet_in generated through one + * uses OFPR_NO_MATCH as its reason, whereas packet_ins generated by any other + * rule use OFPR_ACTION.) */ +static inline bool +rule_is_table_miss(const struct rule *rule) +{ + return rule->cr.priority == 0 && cls_rule_is_catchall(&rule->cr); +} + /* A set of actions within a "struct rule". * * |