On Aug 28, 2013, at 11:55 PM, Ben Pfaff <b...@nicira.com> wrote:

> From: Neil Zhu <z...@centecnetworks.com>
> 
> This doesn't include a dpif implementation of groups functionality.  In its
> current form, it is untested.  Before this is committed, it needs some
> more comments and an ovs-ofctl manpage update.
> 
> Signed-off-by: Neil Zhu <z...@centecnetworks.com>
> Co-authored-by: Ben Pfaff <b...@nicira.com>
> Signed-off-by: Ben Pfaff <b...@nicira.com>

I did a review and some initial testing. I'll send an incremental patch
separately for your review. Its all mainly just style issues, but I pointed
out some real issues below.

...
> @@ -1794,6 +1799,7 @@ parse_ofp_flow_stats_request_str(struct 
> ofputil_flow_stats_request *fsr,
>     fsr->cookie_mask = fm.cookie_mask;
>     fsr->match = fm.match;
>     fsr->out_port = fm.out_port;
> +    fsr->out_group = fm.out_group;
>     fsr->table_id = fm.table_id;
>     return NULL;
> }
> @@ -1878,3 +1884,257 @@ exit:
>     }
>     return error;
> }
> +
> +static char * WARN_UNUSED_RESULT
> +parse_bucket_str(struct ofputil_bucket *p_bucket, char *str_,
> +                  enum ofputil_protocol *usable_protocols)
> +{
> +    struct ofpbuf ofpacts;
> +    char *pos, *act, *arg;
> +    int n_actions;
> +
> +    p_bucket->weight = 1;
> +    p_bucket->watch_port = OFPP_ANY;
> +    p_bucket->watch_group = OFPG11_ANY;
> +
> +    pos = str_;
> +    n_actions = 0;
> +    ofpbuf_init(&ofpacts, 64);
> +    while (ofputil_parse_key_value(&pos, &act, &arg)) {
> +        char *error = NULL;
> +
> +        if (!strcasecmp(act, "weight")) {

The rest to the file only uses strcmp(), not strcasecmp(), except for
actions. I changed these to strcmp()s.

...
> +static char * WARN_UNUSED_RESULT
> +parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
> +                          char *string,
> +                          enum ofputil_protocol *usable_protocols)
> +{
> +    enum {
> +        F_GROUP_TYPE  = 1 << 0,
> +        F_BUCKETS     = 1 << 1,
> +    } fields;
> +    char *save_ptr = NULL;
> +    char *bkt_str = NULL;
> +    char *next_bkt_str = NULL;
> +    bool had_type = false;
> +    char *name;
> +
> +    *usable_protocols = OFPUTIL_P_OF11_UP;
> +
> +    switch (command) {
> +    case OFPGC11_ADD:
> +        fields = F_GROUP_TYPE | F_BUCKETS;
> +        break;
> +
> +    case OFPGC11_DELETE:
> +        fields = 0;
> +        break;
> +
> +    case OFPGC11_MODIFY:
> +        fields = F_GROUP_TYPE | F_BUCKETS;
> +        break;
> +
> +    default:
> +        NOT_REACHED();
> +    }
> +
> +    memset(&gm, 0, sizeof gm);

This needs to be memset(gm, 0, sizeof *gm) instead. Spotted via
"Illegal instruction" signal...

> +    gm->command = command;
> +    gm->group_id = OFPG_ANY;
> +    list_init(&gm->buckets);
> +    if (command == OFPGC11_DELETE && string[0] == '\0') {
> +        gm->group_id = OFPG_ALL;
> +        return NULL;
> +    }
> +
> +    *usable_protocols = OFPUTIL_P_OF11_UP;
> +
> +    bkt_str = strstr(string, "bucket");
> +    if (fields & F_BUCKETS && bkt_str) {
> +        struct ofputil_bucket *p_bucket = NULL;
> +
> +        *bkt_str = '\0';
> +
> +        while (bkt_str) {
> +            char *error;
> +
> +            bkt_str = strchr(bkt_str + 1, '=');
> +            if (!bkt_str) {
> +                return xstrdup("must specify bucket content");

Here (and elsewhere) already allocated buckets are not freed.
The incremental addresses this.

...
> +int
> +ofputil_decode_group_stats_reply(struct ofpbuf *msg,
> +                                 struct ofputil_group_stats *ogs)
> +{
> +    struct ofp11_bucket_counter *obc;
> +    struct ofp11_group_stats *ogs11;
> +    enum ofpraw raw;
> +    enum ofperr error;
> +    size_t base_len;
> +    size_t length;
> +    size_t i;
> +
> +    if (!msg->size) {
> +        return EOF;
> +    }
> +
> +    error = (msg->l2
> +             ? ofpraw_decode(&raw, msg->l2)
> +             : ofpraw_pull(&raw, msg));
> +    if (error) {
> +        return error;
> +    }
> +
> +    if (raw == OFPRAW_OFPST11_GROUP_REPLY) {
> +        base_len = sizeof *ogs11;
> +        ogs11 = ofpbuf_try_pull(msg, sizeof *ogs11);
> +        ogs->duration_sec = ogs->duration_nsec = UINT32_MAX;
> +    } else if (raw == OFPRAW_OFPST13_GROUP_REPLY) {
> +        struct ofp13_group_stats *ogs13;
> +
> +        base_len = sizeof *ogs13;
> +        ogs13 = ofpbuf_try_pull(msg, sizeof *ogs13);
> +        if (ogs13) {
> +            ogs11 = &ogs13->gs;
> +            ogs->duration_sec = ntohl(ogs13->duration_sec);
> +            ogs->duration_nsec = ntohl(ogs13->duration_nsec);
> +        } else {
> +            ogs11 = NULL;
> +        }
> +    } else {
> +        NOT_REACHED();
> +    }
> +
> +    ogs->group_id = ntohl(ogs11->group_id);
> +    ogs->ref_count = ntohl(ogs11->ref_count);
> +    ogs->packet_count = ntohll(ogs11->packet_count);
> +    ogs->byte_count = ntohll(ogs11->byte_count);
> +

Here ogs11 may be NULL, so these need to be moved down a bit.

> +    if (!ogs11) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %zu leftover bytes at end",
> +                     ofpraw_get_name(raw), msg->size);
> +        return OFPERR_OFPBRC_BAD_LEN;
> +    }
> +    length = ntohs(ogs11->length);
> +    if (length < sizeof base_len) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply claims invalid length %zu",
> +                     ofpraw_get_name(raw), length);
> +        return OFPERR_OFPBRC_BAD_LEN;
> +    }
> +
> 
...
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 820ec34..cfbc240 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -6384,4 +6384,11 @@ const struct ofproto_class ofproto_dpif_class = {
>     NULL,                       /* meter_set */
>     NULL,                       /* meter_get */
>     NULL,                       /* meter_del */
> +    NULL,                       /* group_alloc */
> +    NULL,                       /* group_construct */
> +    NULL,                       /* group_destruct */
> +    NULL,                       /* group_dealloc */
> +    NULL,                       /* group_modify */
> +    NULL,                       /* group_get_stats */
> +    NULL,                       /* group_get_ref_cnt */

I do not see the value of having a separate function for
group_get_ref_cnt, see below:

...
> +static void
> +append_group_stats(struct ofgroup *group, struct list *replies)
> +{
> +    struct ofputil_group_stats ogs;
> +    struct ofproto *ofproto = group->ofproto;
> +    long long int now = time_msec();
> +    int error;
> +
> +    error = (ofproto->ofproto_class->group_get_stats
> +             ? ofproto->ofproto_class->group_get_stats(group, &ogs)
> +             : EOPNOTSUPP);
> +    if (error) {
> +        ogs.packet_count = UINT64_MAX;
> +        ogs.byte_count = UINT64_MAX;
> +        ogs.n_buckets = group->n_buckets;
> +        memset(ogs.bucket_stats, 0xff,
> +               ogs.n_buckets * sizeof *ogs.bucket_stats);
> +    }
> +
> +    error = (ofproto->ofproto_class->group_get_ref_cnt
> +             ? ofproto->ofproto_class->group_get_ref_cnt(group, 
> &ogs.ref_count)
> +             : EOPNOTSUPP);
> +    if (error) {
> +        ogs.ref_count = UINT32_MAX;
> +    }
> +

It would be simper just to have the group_get_stats return also the
ref_cnt, which is part of the stats structure anyway. In case the ofproto
provider does not support ref_cnt, it can return it as UINT32_MAX to
retain the behavior here.

Also, it seems to me that the reference counting should be implemented
in the ofproto proper anyway, rather than in an ofproto-provider. In the
incremental I have removed the group_get_ref_cnt().

  Jarno
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to