On Tue, May 10, 2011 at 06:18:08PM -0700, Ethan Jackson wrote:
> @@ -174,6 +174,11 @@ struct action_xlate_ctx {
>       * its actions.  If special_cb returns false on 'flow' rendered
>       * uninstallable and no actions will be executed. */
>      bool check_special;
> +    /* This is probably not the patch to fix it, but I'm pretty sure that
> +     * check_special is dead code now.  Doing some research, it apparently 
> has
> +     * been since ofproto_send_packet() no longer had to call 
> xlate_actions().
> +     * I don't think this is worth fixing on master, but it may be worth 
> adding
> +     * a patch to the end of the next branch which cleans it up. */
>  

OK, I sent out a patch (and you already reviewed it).

>  /* xlate_actions() initializes and uses these members.  The client might want
>   * to look at them after it returns. */
> @@ -1400,6 +1405,9 @@ port_del(struct ofproto *ofproto_, uint16_t ofp_port)
>           * it from the bond before closing the netdev.  The client will need 
> to
>           * reconfigure everything after deleting ports, so then the slave 
> will
>           * get re-added. */
> +        /* I don't fully understand this comment.  You don't ever close the
> +         * netdev in this function.  Do you intend to, or does it happen
> +         * somewhere else? */
>          struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port);
>          if (ofport) {
>              bundle_remove(&ofport->up);

The comment is wrong, but the issue is real.

I rewrote it like this:

    error = dpif_port_del(ofproto->dpif, ofp_port_to_odp_port(ofp_port));
    if (!error) {
        struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port);
        if (ofport) {
            /* The caller is going to close ofport->up.netdev.  If this is a
             * bonded port, then the bond is using that netdev, so remove it
             * from the bond.  The client will need to reconfigure everything
             * after deleting ports, so then the slave will get re-added. */
            bundle_remove(&ofport->up);
        }
    }

> @@ -1714,6 +1722,8 @@ update_stats(struct ofproto_dpif *p)
>  
>              if (stats->n_packets >= facet->dp_packet_count) {
>                  facet->packet_count += stats->n_packets - 
> facet->dp_packet_count;
> +                /* The above line is too long.  It was too long in the old
> +                 * version as well, but may as well fix it. */

OK, I added a temporary.

>              } else {
>                  VLOG_WARN_RL(&rl, "unexpected packet count from the 
> datapath");
>              }
> @@ -2472,6 +2482,10 @@ rule_destruct(struct rule *rule_)
>      LIST_FOR_EACH_SAFE (facet, next_facet, list_node, &rule->facets) {
>          facet_revalidate(ofproto, facet);
>      }
> +    /* I may be thinking about this incorrectly.  I think rule destruction
> +     * requires ofproto->need_revalidate = true because of resubmits.  Theres
> +     * no way to predict which facets resubmit into 'rule_' and thus need 
> their
> +     * actions recalculation. */
>  }

I think you're right.  I changed this to set need_revalidate.

In a later patch this rule_destruct() and rule_remove() get combined,
IIRC.  rule_remove() already sets need_revalidate, so this becomes a
bit more natural at that point.

>  static void
> @@ -2545,6 +2559,10 @@ rule_execute(struct rule *rule_, struct flow *flow, 
> struct ofpbuf *packet)
>      ofpbuf_delete(odp_actions);
>  }
>  
> +/* The name of this function makes one think that it should actually be 
> setting
> + * the ofp_actions in 'rule_'.  Apparently, it only validates that the 
> actions
> + * are reasonable.  I can't tell if this is a mistake in the implementation, 
> or
> + * just a case of insufficient documentation. */

It's just insufficient documentation in this case.  A patch in next2
adds documentation:

+    /* Validates that the 'n' elements in 'actions' are well-formed OpenFlow
+     * actions that can be correctly implemented by the datapath.  If not, then
+     * return an OpenFlow error code (as returned by ofp_mkerr()).  If so,
+     * then update the datapath to implement the new actions and return 0.
+     *
+     * When this function runs, 'rule' still has its original actions.  If this
+     * function returns 0, then the caller will update 'rule' with the new
+     * actions and free the old ones. */

Sorry about that.  Lack of documentation probably made this patch
harder to review than necessary.

> @@ -2846,6 +2864,7 @@ xlate_autopath(struct action_xlate_ctx *ctx,
>  {
>      uint16_t ofp_port = ntohl(naa->id);
>      struct ofport_dpif *port = get_ofp_port(ctx->ofproto, ofp_port);
> +
>      if (!port || !port->bundle) {
>          ofp_port = OFPP_NONE;
>      } else if (port->bundle->bond) {

OK, I added a blank line here.

> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index 57d4116..ec07895 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -200,6 +200,8 @@ ofproto_class_unregister(const struct ofproto_class 
> *class)
>  {
>      size_t i;
>  
> +    /* Why do we need to maintaion the order of ofproto_classes?  Seems fine,
> +     * just curious. */

Order doesn't matter with other OVS classes (e.g. netdev, dpif)
because each one can only implement a single type, and duplicate types
are not allowed.  So, ordering doesn't matter, because there can be no
overlap.

An ofproto_class is different: it can implement several types, the
types that it implements are allowed to change
(e.g. ofproto_dpif_class's implemented types will change as dpif
classes are registered and unregistered), and there's no attempt to
ensure that they don't overlap.  Therefore, order can matter, so I
decided that we might as well maintain the existing order on
unregister to avoid weird surprises.

> @@ -541,7 +543,10 @@ ofproto_port_is_lacp_current(struct ofproto *ofproto, 
> uint16_t ofp_port)
>   * to 's'.  Otherwise, this function registers a new bundle.
>   *
>   * Bundles affect only the treatment of packets output to the OFPP_NORMAL
> - * port.  */
> + * port.
> + *
> + * This isn't true.  Bundles affect the autopath action as well.
> + */

OK, I added a mention.

>  int
>  ofproto_bundle_register(struct ofproto *ofproto, void *aux,
>                          const struct ofproto_bundle_settings *s)
> @@ -1271,6 +1276,10 @@ rule_create(struct ofproto *ofproto, const struct 
> cls_rule *cls_rule,
>      if (n_actions > 0) {
>          rule->n_actions = n_actions;
>          rule->actions = xmemdup(actions, n_actions * sizeof *actions);
> +    } else {
> +        /* I think this is required because rule_alloc() doesn't zero. */
> +        rule->n_actions = 0;
> +        rule->actions = NULL;
>      }

Good catch.  I changed this code to:
    if (n_actions > 0) {
        rule->actions = xmemdup(actions, n_actions * sizeof *actions);
    } else {
        rule->actions = NULL;
    }
    rule->n_actions = n_actions;

> @@ -1960,6 +1969,7 @@ flow_stats_ds(struct rule *rule, struct ds *results)
>  
>      ds_put_format(results, "duration=%llds, ",
>                    (time_msec() - rule->created) / 1000);
> +    /* I'm not sure if you intend to delete this line or uncomment it. */
>      //ds_put_format(results, "idle=%.3fs, ", (time_msec() - rule->used) / 
> 1000.0);

I wasn't really sure what to do here.  OpenFlow doesn't provide any
way to find out how long a flow has been idle, so I didn't have an a
priori reason to add such an interface to the ofproto_class.

For now I've deleted it.

>      ds_put_format(results, "priority=%u, ", rule->cr.priority);
>      ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
> diff --git a/ofproto/private.h b/ofproto/private.h
> index d79ed81..1ab8c6c 100644
> --- a/ofproto/private.h
> +++ b/ofproto/private.h
> @@ -14,6 +14,11 @@
>   * limitations under the License.
>   */
>  
> +/* I think it would be a good idea to have someone with hardware experience 
> to
> + * read over this file in addition to me to make sure it's relatively easy to
> + * port.  I don't see a reason why it wouldn't be, but I have no experience
> + * with hardware so it might be worth having another pair of eyes on it. */

Yeah, I've been asking for someone with hardware experience to comment
on various interfaces I proposed literally for *YEARS*.  But hardware
people apparently don't have opinions, or at least they don't share
them.

I'm not holding my breath.

>  #ifndef OFPROTO_PRIVATE_H
>  #define OFPROTO_PRIVATE_H 1
>  
> @@ -100,6 +105,7 @@ struct rule *ofproto_rule_lookup(struct ofproto *, const 
> struct flow *);
>  void ofproto_rule_expire(struct rule *, uint8_t reason);
>  void ofproto_rule_destroy(struct rule *);
>  
> +/* This comment is awesome. */

Thanks.  I've dealt with far too many libraries that just don't
document expectations.  I didn't want to make the same mistake.

>  /* ofproto class structure, to be defined by each ofproto implementation.
>   *
>   *
> @@ -168,7 +174,7 @@ void ofproto_rule_destroy(struct rule *);
>   * use of the new data structure, so it cannot perform much initialization.
>   * Its purpose is just to ensure that the new data structure has enough room
>   * for base and derived state.  It may return a null pointer if memory is not
> - * available, in which case none of the other functions is called.
> + * available, in which case none of the other functions are called.

I'm pretty sure that "none" is singular.

>   * Each "construct" function initializes derived state in its respective data
>   * structure.  When "construct" is called, all of the base state has already
> @@ -246,7 +252,7 @@ struct ofproto_class {
>       * poll-loop.h.  */
>      void (*wait)(struct ofproto *ofproto);
>  
> -    /* Every "struct rule"s in 'ofproto' is about to be deleted, one by one.
> +    /* Every "struct rule" in 'ofproto' is about to be deleted, one by one.

Thanks, fixed.

>       * This function may prepare for that, for example by clearing state in
>       * advance.  It should *not* actually delete any "struct rule"s from
>       * 'ofproto', only prepare for it.
> @@ -387,6 +393,10 @@ struct ofproto_class {
>  
>      void (*rule_remove)(struct rule *rule);
>  
> +    /* It's not clear to me why the next couple of functions, and
> +     * port_is_lacp_current() above don't get comments.  When reading this, I
> +     * would have found a comment on rule_execute() and rule_modify_actions()
> +     * useful in particular. */
>      void (*rule_get_stats)(struct rule *rule, uint64_t *packet_count,
>                             uint64_t *byte_count);

I just ran out of time.  Commit "ofproto: Better document the
ofproto_class interface" in next2 adds the missing comments.

> @@ -458,9 +468,12 @@ struct ofproto_class {
>       * has been registered, this has no effect.
>       *
>       * This function affects only the behavior of the OFPP_NORMAL action.  An
> -     * implementation that does not to support it at all may set it to NULL 
> or
> +     * implementation that does not support it at all may set it to NULL or
>       * return EOPNOTSUPP.  An implementation that supports only a subset of 
> the
> -     * functionality should implement what it can and return 0. */
> +     * functionality should implement what it can and return 0.
> +     *
> +     * It affects the behavior of the autopath action as well.
> +     * */
>      int (*bundle_set)(struct ofproto *ofproto, void *aux,
>                        const struct ofproto_bundle_settings *s);
>  

OK, I revised this comment and the others that you pointed out.
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to