Hi,

I am somewhat confused about this patch.

I became confused while trying to make use of pin->generated_by_table_miss
to drop controller actions in connmgr_send_packet_in()
for OpenFlow1.3 if its default table-miss policy is in effect.

I have successfully implemented a prototype pf that logic.
But my confusion about this patch remains.

On Tue, Oct 22, 2013 at 10:05:19PM -0700, Ben Pfaff wrote:
> From: YAMAMOTO Takashi <yamam...@valinux.co.jp>
> 
> 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>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  OPENFLOW-1.1+                 |    3 ---
>  ofproto/connmgr.c             |   32 ++++++++++++++++++++++++++++----
>  ofproto/connmgr.h             |    5 +++++
>  ofproto/fail-open.c           |    1 +
>  ofproto/ofproto-dpif-upcall.c |    1 +
>  ofproto/ofproto-dpif-xlate.c  |    2 ++
>  ofproto/ofproto-dpif.c        |    5 +++++
>  ofproto/ofproto-dpif.h        |    1 +
>  ofproto/ofproto-provider.h    |   12 ++++++++++++
>  9 files changed, 55 insertions(+), 7 deletions(-)
> 
> diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+
> index 22be72c..bd6ced6 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.

Looking over the spec, it seems to me that OpenFlow1.0, 1,1 or 1.2
should also use OFPR_NO_MATCH. 

Furthermore it seems to me, looking at the current master branch, which is
admittedly about a month more recent than this patch, that Open vSwtich
uses OFPR_NO_MATCH regardless of the Open Flow version used.

I base this on the assumption that miss-rules are added by
add_internal_flow().  That function adds rules with controller actions with
the reason set to OFPR_NO_MATCH.

>        [required for OF1.3+]
>  
>      * IPv6 extension header handling support.  Fully implementing this
> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
> index f5bef59..d42ab4f 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 e9ffbbc..10caaf4 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 b0caf8d..bae9dca 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 491f11e..24a5729 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 ed9ca7c..1eb0953 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 67c21f5..be7f807 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 ab5dfbb..c93d37c 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 de566e3..07bb266 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);
> +}
> +

Again assuming that miss-rules are added by add_internal_flow().

add_internal_flows() adds rules with the mask of register 0 set to
all 1s due to the following line in add_internal_flow().

    match_set_reg(&fm.match, 0, id);

So I believe that rule_is_table_miss() will not return true for
miss-rules. I believe that the following will, though perhaps it
is too broad.

    return rule->table_id == TBL_INTERNAL;

>  /* A set of actions within a "struct rule".
>   *
>   *
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to