static void delete_flow__(struct rule *rule, struct ofopgroup *,
enum ofp_flow_removed_reason)
OVS_REQUIRES(ofproto_mutex);
+static bool ofproto_group_exists(const struct ofproto *ofproto,
+ uint32_t group_id)
+ OVS_REQ_RDLOCK(ofproto->groups_rwlock);
static enum ofperr add_group(struct ofproto *, struct ofputil_group_mod *);
static bool handle_openflow(struct ofconn *, const struct ofpbuf *);
static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *,
*/
static enum ofperr
ofproto_check_ofpacts(struct ofproto *ofproto,
- const struct ofpact ofpacts[], size_t ofpacts_len,
+ struct ofpact ofpacts[], size_t ofpacts_len,
struct flow *flow, uint8_t table_id,
const struct ofp_header *oh)
{
enum ofperr error;
+ const struct ofpact *a;
uint32_t mid;
error = ofpacts_check(ofpacts, ofpacts_len, flow,
return error;
}
+ OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ if (a->type == OFPACT_GROUP) {
+ bool exists;
+
+ ovs_rwlock_rdlock(&ofproto->groups_rwlock);
+ exists = ofproto_group_exists(ofproto,
+ ofpact_get_GROUP(a)->group_id);
+ ovs_rwlock_unlock(&ofproto->groups_rwlock);
+
+ if (!exists) {
+ return OFPERR_OFPBAC_BAD_OUT_GROUP;
+ }
+ }
+ }
+
mid = ofpacts_get_meter(ofpacts, ofpacts_len);
if (mid && get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
return OFPERR_OFPMMFC_INVALID_METER;
return false;
}
+static uint32_t
+group_get_ref_count(struct ofgroup *group)
+ OVS_EXCLUDED(ofproto_mutex)
+{
+ struct ofproto *ofproto = group->ofproto;
+ struct rule_criteria criteria;
+ struct rule_collection rules;
+ struct match match;
+ enum ofperr error;
+ uint32_t count;
+
+ match_init_catchall(&match);
+ rule_criteria_init(&criteria, 0xff, &match, 0, htonll(0), htonll(0),
+ OFPP_ANY, group->group_id);
+ ovs_mutex_lock(&ofproto_mutex);
+ error = collect_rules_loose(ofproto, &criteria, &rules);
+ ovs_mutex_unlock(&ofproto_mutex);
+ rule_criteria_destroy(&criteria);
+
+ count = !error && rules.n < UINT32_MAX ? rules.n : UINT32_MAX;
+
+ rule_collection_destroy(&rules);
+ return count;
+}
+
static void
append_group_stats(struct ofgroup *group, struct list *replies)
OVS_REQ_RDLOCK(group->rwlock)
ogs.bucket_stats = xmalloc(group->n_buckets * sizeof *ogs.bucket_stats);
+ /* Provider sets the packet and byte counts, we do the rest. */
+ ogs.ref_count = group_get_ref_count(group);
+ ogs.n_buckets = group->n_buckets;
+
error = (ofproto->ofproto_class->group_get_stats
? ofproto->ofproto_class->group_get_stats(group, &ogs)
: EOPNOTSUPP);
if (error) {
- ogs.ref_count = UINT32_MAX;
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);
}