const struct mf_subfield *fields,
size_t n_fields);
-static void oftable_remove_rule(struct rule *rule) OVS_RELEASES(rule->evict);
+static void oftable_remove_rule(struct rule *rule) OVS_RELEASES(rule->rwlock);
static void oftable_remove_rule__(struct ofproto *ofproto,
struct classifier *cls, struct rule *rule)
- OVS_REQ_WRLOCK(cls->rwlock) OVS_RELEASES(rule->evict);
+ OVS_REQ_WRLOCK(cls->rwlock) OVS_RELEASES(rule->rwlock);
static void oftable_insert_rule(struct rule *);
/* A set of rules within a single OpenFlow table (oftable) that have the same
};
static bool choose_rule_to_evict(struct oftable *table, struct rule **rulep)
- OVS_TRY_WRLOCK(true, (*rulep)->evict);
+ OVS_TRY_WRLOCK(true, (*rulep)->rwlock);
static void ofproto_evict(struct ofproto *);
static uint32_t rule_eviction_priority(struct rule *);
static void eviction_group_add_rule(struct rule *);
const struct ofp_header *, struct list *);
static void delete_flow__(struct rule *rule, struct ofopgroup *,
enum ofp_flow_removed_reason)
- OVS_RELEASES(rule->evict);
+ OVS_RELEASES(rule->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 *,
group = ofopgroup_create_unattached(ofproto);
ofoperation_create(group, rule, OFOPERATION_DELETE, OFPRR_DELETE);
- ovs_rwlock_wrlock(&rule->evict);
+ ovs_rwlock_wrlock(&rule->rwlock);
oftable_remove_rule__(ofproto, cls, rule);
ofproto->ofproto_class->rule_delete(rule);
ofopgroup_submit(group);
cls_rule_destroy(&rule->cr);
free(rule->ofpacts);
ovs_mutex_destroy(&rule->timeout_mutex);
- ovs_rwlock_destroy(&rule->evict);
+ ovs_rwlock_destroy(&rule->rwlock);
rule->ofproto->ofproto_class->rule_dealloc(rule);
}
}
if (new_cookie != rule->flow_cookie) {
cookies_remove(ofproto, rule);
+ ovs_rwlock_wrlock(&rule->rwlock);
rule->flow_cookie = new_cookie;
+ ovs_rwlock_unlock(&rule->rwlock);
cookies_insert(ofproto, rule);
}
} else if (!choose_rule_to_evict(table, &rule)) {
return OFPERR_OFPFMFC_TABLE_FULL;
} else if (rule->pending) {
- ovs_rwlock_unlock(&rule->evict);
+ ovs_rwlock_unlock(&rule->rwlock);
return OFPROTO_POSTPONE;
} else {
struct ofopgroup *group;
rule->monitor_flags = 0;
rule->add_seqno = 0;
rule->modify_seqno = 0;
- ovs_rwlock_init(&rule->evict);
+ ovs_rwlock_init(&rule->rwlock);
/* Construct rule, initializing derived state. */
error = ofproto->ofproto_class->rule_construct(rule);
op->ofpacts = rule->ofpacts;
op->ofpacts_len = rule->ofpacts_len;
op->meter_id = rule->meter_id;
+
+ ovs_rwlock_wrlock(&rule->rwlock);
rule->ofpacts = xmemdup(fm->ofpacts, fm->ofpacts_len);
rule->ofpacts_len = fm->ofpacts_len;
+ ovs_rwlock_unlock(&rule->rwlock);
+
rule->meter_id = find_meter(rule->ofpacts, rule->ofpacts_len);
rule->ofproto->ofproto_class->rule_modify_actions(rule,
reset_counters);
group = ofopgroup_create(ofproto, ofconn, request, UINT32_MAX);
LIST_FOR_EACH_SAFE (rule, next, ofproto_node, rules) {
- ovs_rwlock_wrlock(&rule->evict);
+ ovs_rwlock_wrlock(&rule->rwlock);
delete_flow__(rule, group, reason);
}
ofopgroup_submit(group);
return 0;
}
+static enum ofperr
+handle_nxt_get_async_request(struct ofconn *ofconn, const struct ofp_header *oh)
+{
+ struct ofpbuf *buf;
+ uint32_t master[OAM_N_TYPES];
+ uint32_t slave[OAM_N_TYPES];
+ struct nx_async_config *msg;
+
+ ofconn_get_async_config(ofconn, master, slave);
+ buf = ofpraw_alloc_reply(OFPRAW_OFPT13_GET_ASYNC_REPLY, oh, 0);
+ msg = ofpbuf_put_zeros(buf, sizeof *msg);
+
+ msg->packet_in_mask[0] = htonl(master[OAM_PACKET_IN]);
+ msg->port_status_mask[0] = htonl(master[OAM_PORT_STATUS]);
+ msg->flow_removed_mask[0] = htonl(master[OAM_FLOW_REMOVED]);
+
+ msg->packet_in_mask[1] = htonl(slave[OAM_PACKET_IN]);
+ msg->port_status_mask[1] = htonl(slave[OAM_PORT_STATUS]);
+ msg->flow_removed_mask[1] = htonl(slave[OAM_FLOW_REMOVED]);
+
+ ofconn_send_reply(ofconn, buf);
+
+ return 0;
+}
+
static enum ofperr
handle_nxt_set_controller_id(struct ofconn *ofconn,
const struct ofp_header *oh)
long long int now = time_msec();
int error;
+ ogs.bucket_stats = xmalloc(group->n_buckets * sizeof *ogs.bucket_stats);
+
error = (ofproto->ofproto_class->group_get_stats
? ofproto->ofproto_class->group_get_stats(group, &ogs)
: EOPNOTSUPP);
calc_duration(group->created, now, &ogs.duration_sec, &ogs.duration_nsec);
ofputil_append_group_stats(replies, &ogs);
+
+ free(ogs.bucket_stats);
}
static enum ofperr
}
}
+static enum ofperr
+handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
+{
+ struct ofputil_table_mod tm;
+ enum ofperr error;
+
+ error = reject_slave_controller(ofconn);
+ if (error) {
+ return error;
+ }
+
+ error = ofputil_decode_table_mod(oh, &tm);
+ if (error) {
+ return error;
+ }
+
+ /* XXX Actual table mod support is not implemented yet. */
+ return 0;
+}
+
static enum ofperr
handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
{
case OFPTYPE_GROUP_MOD:
return handle_group_mod(ofconn, oh);
+ case OFPTYPE_TABLE_MOD:
+ return handle_table_mod(ofconn, oh);
+
case OFPTYPE_METER_MOD:
return handle_meter_mod(ofconn, oh);
case OFPTYPE_SET_ASYNC_CONFIG:
return handle_nxt_set_async_config(ofconn, oh);
+ case OFPTYPE_GET_ASYNC_REQUEST:
+ return handle_nxt_get_async_request(ofconn, oh);
+
/* Statistics requests. */
case OFPTYPE_DESC_STATS_REQUEST:
return handle_desc_stats_request(ofconn, oh);
/* FIXME: Change the following once they are implemented: */
case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
- case OFPTYPE_GET_ASYNC_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
return OFPERR_OFPBRC_BAD_TYPE;
}
}
} else {
- ovs_rwlock_wrlock(&rule->evict);
+ ovs_rwlock_wrlock(&rule->rwlock);
oftable_remove_rule(rule);
ofproto_rule_destroy__(rule);
}
ovs_mutex_unlock(&rule->timeout_mutex);
if (op->ofpacts) {
free(rule->ofpacts);
+
+ ovs_rwlock_wrlock(&rule->rwlock);
rule->ofpacts = op->ofpacts;
rule->ofpacts_len = op->ofpacts_len;
+ ovs_rwlock_unlock(&rule->rwlock);
+
op->ofpacts = NULL;
op->ofpacts_len = 0;
}
struct rule *rule;
HEAP_FOR_EACH (rule, evg_node, &evg->rules) {
- if (!ovs_rwlock_trywrlock(&rule->evict)) {
+ if (!ovs_rwlock_trywrlock(&rule->rwlock)) {
*rulep = rule;
return true;
}
}
if (rule->pending) {
- ovs_rwlock_unlock(&rule->evict);
+ ovs_rwlock_unlock(&rule->rwlock);
break;
}
static void
oftable_remove_rule__(struct ofproto *ofproto, struct classifier *cls,
struct rule *rule)
- OVS_REQ_WRLOCK(cls->rwlock) OVS_RELEASES(rule->evict)
+ OVS_REQ_WRLOCK(cls->rwlock) OVS_RELEASES(rule->rwlock)
{
classifier_remove(cls, &rule->cr);
cookies_remove(ofproto, rule);
list_remove(&rule->meter_list_node);
list_init(&rule->meter_list_node);
}
- ovs_rwlock_unlock(&rule->evict);
+ ovs_rwlock_unlock(&rule->rwlock);
}
static void