text: /*
   * Copyright (c) 2008-2017 Nicira, Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at:
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #ifndef OPENVSWITCH_OFP_GROUP_H
  #define OPENVSWITCH_OFP_GROUP_H 1
  
  #include "openflow/openflow.h"
  #include "openflow/netronome-ext.h"
  #include "openvswitch/list.h"
  #include "openvswitch/meta-flow.h"
  #include "openvswitch/type-props.h"
  
  struct ds;
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  struct ofputil_table_map;
  
  /* Group numbers. */
  enum { MAX_GROUP_NAME_LEN = INT_STRLEN(uint32_t) };
  bool ofputil_group_from_string(const char *, uint32_t *group_id);
  void ofputil_format_group(uint32_t group_id, struct ds *);
  void ofputil_group_to_string(uint32_t group_id,
                               char namebuf[MAX_GROUP_NAME_LEN + 1],
                               size_t bufsize);
  
  struct bucket_counter {
      uint64_t packet_count;   /* Number of packets processed by bucket. */
      uint64_t byte_count;     /* Number of bytes processed by bucket. */
  };
  
  /* Bucket for use in groups. */
  struct ofputil_bucket {
      struct ovs_list list_node;
      uint16_t weight;            /* Relative weight, for "select" groups. */
      ofp_port_t watch_port;      /* Port whose state affects whether this bucket
                                   * is live. Only required for fast failover
                                   * groups. */
      uint32_t watch_group;       /* Group whose state affects whether this
                                   * bucket is live. Only required for fast
                                   * failover groups. */
      uint32_t bucket_id;         /* Bucket Id used to identify bucket*/
      struct ofpact *ofpacts;     /* Series of "struct ofpact"s. */
      size_t ofpacts_len;         /* Length of ofpacts, in bytes. */
  
      struct bucket_counter stats;
  };
  
  void ofputil_bucket_list_destroy(struct ovs_list *buckets);
  void ofputil_bucket_clone_list(struct ovs_list *dest,
                                 const struct ovs_list *src,
                                 const struct ofputil_bucket *);
  struct ofputil_bucket *ofputil_bucket_find(const struct ovs_list *,
                                             uint32_t bucket_id);
  bool ofputil_bucket_check_duplicate_id(const struct ovs_list *);
  struct ofputil_bucket *ofputil_bucket_list_front(const struct ovs_list *);
  struct ofputil_bucket *ofputil_bucket_list_back(const struct ovs_list *);
  
  static inline bool
  ofputil_bucket_has_liveness(const struct ofputil_bucket *bucket)
  {
      return (bucket->watch_port != OFPP_ANY ||
              bucket->watch_group != OFPG_ANY);
  }
  
  struct ofputil_group_props {
      /* NTR selection method */
      char selection_method[NTR_MAX_SELECTION_METHOD_LEN];
      uint64_t selection_method_param;
      struct field_array fields;
  };
  
  void ofputil_group_properties_destroy(struct ofputil_group_props *);
  void ofputil_group_properties_copy(struct ofputil_group_props *to,
                                     const struct ofputil_group_props *from);
  /* Protocol-independent group_mod. */
  struct ofputil_group_mod {
      uint16_t command;             /* One of OFPGC15_*. */
      uint8_t type;                 /* One of OFPGT11_*. */
      uint32_t group_id;            /* Group identifier. */
      uint32_t command_bucket_id;   /* Bucket Id used as part of
                                     * OFPGC15_INSERT_BUCKET and
                                     * OFPGC15_REMOVE_BUCKET commands
                                     * execution.*/
      struct ovs_list buckets;      /* Contains "struct ofputil_bucket"s. */
      struct ofputil_group_props props; /* Group properties. */
  };
  
  void ofputil_uninit_group_mod(struct ofputil_group_mod *gm);
  struct ofpbuf *ofputil_encode_group_mod(enum ofp_version ofp_version,
                                          const struct ofputil_group_mod *gm,
                                          const struct ovs_list *new_buckets,
                                          int group_existed);
  
  enum ofperr ofputil_decode_group_mod(const struct ofp_header *,
                                       struct ofputil_group_mod *);
  
  void ofputil_group_mod_format__(struct ds *, enum ofp_version,
                                  const struct ofputil_group_mod *,
                                  const struct ofputil_port_map *,
                                  const struct ofputil_table_map *);
  enum ofperr ofputil_group_mod_format(struct ds *, const struct ofp_header *,
                                       const struct ofputil_port_map *,
                                       const struct ofputil_table_map *);
  
  char *parse_ofp_group_mod_file(const char *file_name,
                                 const struct ofputil_port_map *,
                                 const struct ofputil_table_map *, int command,
                                 struct ofputil_group_mod **gms, size_t *n_gms,
                                 enum ofputil_protocol *usable_protocols)
      OVS_WARN_UNUSED_RESULT;
  
  char *parse_ofp_group_mod_str(struct ofputil_group_mod *, int command,
                                const char *string,
                                const struct ofputil_port_map *,
                                const struct ofputil_table_map *,
                                enum ofputil_protocol *usable_protocols)
      OVS_WARN_UNUSED_RESULT;
  
  /* Group stats reply, independent of protocol. */
  struct ofputil_group_stats {
      uint32_t group_id;    /* Group identifier. */
      uint32_t ref_count;
      uint64_t packet_count;      /* Packet count, UINT64_MAX if unknown. */
      uint64_t byte_count;        /* Byte count, UINT64_MAX if unknown. */
      uint32_t duration_sec;      /* UINT32_MAX if unknown. */
      uint32_t duration_nsec;
      uint32_t n_buckets;
      struct bucket_counter *bucket_stats;
  };
  
  struct ofpbuf *ofputil_encode_group_stats_request(enum ofp_version,
                                                    uint32_t group_id);
  enum ofperr ofputil_decode_group_stats_request(
      const struct ofp_header *request, uint32_t *group_id);
  void ofputil_append_group_stats(struct ovs_list *replies,
                                  const struct ofputil_group_stats *);
  enum ofperr ofputil_group_stats_request_format(struct ds *,
                                                 const struct ofp_header *);
  
  int ofputil_decode_group_stats_reply(struct ofpbuf *,
                                       struct ofputil_group_stats *);
  enum ofperr ofputil_group_stats_format(struct ds *, const struct ofp_header *);
  
  /* Group features reply, independent of protocol.
   *
   * Only OF1.2 and later support group features replies. */
  struct ofputil_group_features {
      uint32_t  types;           /* Bitmap of OFPGT_* values supported. */
      uint32_t  capabilities;    /* Bitmap of OFPGFC12_* capability supported. */
      uint32_t  max_groups[4];   /* Maximum number of groups for each type. */
      uint64_t  ofpacts[4];      /* Bitmaps of supported OFPACT_* */
  };
  
  struct ofpbuf *ofputil_encode_group_features_request(enum ofp_version);
  struct ofpbuf *ofputil_encode_group_features_reply(
      const struct ofputil_group_features *, const struct ofp_header *request);
  void ofputil_decode_group_features_reply(const struct ofp_header *,
                                           struct ofputil_group_features *);
  
  /* Group desc reply, independent of protocol. */
  struct ofputil_group_desc {
      uint8_t type;               /* One of OFPGT_*. */
      uint32_t group_id;          /* Group identifier. */
      struct ovs_list buckets;    /* Contains "struct ofputil_bucket"s. */
      struct ofputil_group_props props; /* Group properties. */
  };
  
  void ofputil_uninit_group_desc(struct ofputil_group_desc *gd);
  uint32_t ofputil_decode_group_desc_request(const struct ofp_header *);
  struct ofpbuf *ofputil_encode_group_desc_request(enum ofp_version,
                                                   uint32_t group_id);
  enum ofperr ofputil_group_desc_request_format(struct ds *,
                                                const struct ofp_header *);
  
  int ofputil_decode_group_desc_reply(struct ofputil_group_desc *,
                                      struct ofpbuf *, enum ofp_version);
  void ofputil_append_group_desc_reply(const struct ofputil_group_desc *,
                                       const struct ovs_list *buckets,
                                       struct ovs_list *replies);
  enum ofperr ofputil_group_desc_format(struct ds *, const struct ofp_header *,
                                        const struct ofputil_port_map *,
                                        const struct ofputil_table_map *);
  enum ofperr ofputil_group_features_format(struct ds *,
                                            const struct ofp_header *);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif  /* ofp-group.h */
  