diff options
Diffstat (limited to 'ofproto/ofproto.c')
-rw-r--r-- | ofproto/ofproto.c | 168 |
1 files changed, 108 insertions, 60 deletions
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 5ab7391a8..50b9ec6f6 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2777,6 +2777,103 @@ handle_echo_request(struct ofconn *ofconn, const struct ofp_header *oh) return 0; } +static void +query_tables(struct ofproto *ofproto, + struct ofputil_table_features **featuresp, + struct ofputil_table_stats **statsp) +{ + struct mf_bitmap rw_fields = MF_BITMAP_INITIALIZER; + struct ofputil_table_features *features; + struct ofputil_table_stats *stats; + int i; + + for (i = 0; i < MFF_N_IDS; i++) { + if (mf_from_id(i)->writable) { + bitmap_set1(rw_fields.bm, i); + } + } + + features = *featuresp = xcalloc(ofproto->n_tables, sizeof *features); + for (i = 0; i < ofproto->n_tables; i++) { + struct ofputil_table_features *f = &features[i]; + unsigned int config; + + f->table_id = i; + sprintf(f->name, "table%d", i); + f->metadata_match = OVS_BE64_MAX; + f->metadata_write = OVS_BE64_MAX; + atomic_read(&ofproto->tables[i].config, &config); + f->config = config; + f->max_entries = 1000000; + + bitmap_set_multiple(f->nonmiss.next, i + 1, + ofproto->n_tables - (i + 1), true); + f->nonmiss.instructions = (1u << N_OVS_INSTRUCTIONS) - 1; + if (i == ofproto->n_tables - 1) { + f->nonmiss.instructions &= ~(1u << OVSINST_OFPIT11_GOTO_TABLE); + } + f->nonmiss.write.ofpacts = (UINT64_C(1) << N_OFPACTS) - 1; + f->nonmiss.write.set_fields = rw_fields; + f->nonmiss.apply = f->nonmiss.write; + f->miss = f->nonmiss; + + bitmap_set_multiple(f->match.bm, 0, MFF_N_IDS, 1); + bitmap_set_multiple(f->mask.bm, 0, MFF_N_IDS, 1); + bitmap_set_multiple(f->wildcard.bm, 0, MFF_N_IDS, 1); + } + + if (statsp) { + stats = *statsp = xcalloc(ofproto->n_tables, sizeof *stats); + for (i = 0; i < ofproto->n_tables; i++) { + struct ofputil_table_stats *s = &stats[i]; + struct classifier *cls = &ofproto->tables[i].cls; + + s->table_id = i; + s->active_count = classifier_count(cls); + } + } else { + stats = NULL; + } + + ofproto->ofproto_class->query_tables(ofproto, features, stats); + + for (i = 0; i < ofproto->n_tables; i++) { + const struct oftable *table = &ofproto->tables[i]; + struct ofputil_table_features *f = &features[i]; + + if (table->name) { + ovs_strzcpy(f->name, table->name, sizeof f->name); + } + + if (table->max_flows < f->max_entries) { + f->max_entries = table->max_flows; + } + } +} + +static void +query_switch_features(struct ofproto *ofproto, + bool *arp_match_ip, uint64_t *ofpacts) +{ + struct ofputil_table_features *features, *f; + + *arp_match_ip = false; + *ofpacts = 0; + + query_tables(ofproto, &features, NULL); + for (f = features; f < &features[ofproto->n_tables]; f++) { + *ofpacts |= f->nonmiss.apply.ofpacts | f->miss.apply.ofpacts; + if (bitmap_is_set(f->match.bm, MFF_ARP_SPA) || + bitmap_is_set(f->match.bm, MFF_ARP_TPA)) { + *arp_match_ip = true; + } + } + free(features); + + /* Sanity check. */ + ovs_assert(*ofpacts & (UINT64_C(1) << OFPACT_OUTPUT)); +} + static enum ofperr handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) { @@ -2786,9 +2883,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) bool arp_match_ip; struct ofpbuf *b; - ofproto->ofproto_class->get_features(ofproto, &arp_match_ip, - &features.ofpacts); - ovs_assert(features.ofpacts & (UINT64_C(1) << OFPACT_OUTPUT)); + query_switch_features(ofproto, &arp_match_ip, &features.ofpacts); features.datapath_id = ofproto->datapath_id; features.n_buffers = pktbuf_capacity(); @@ -3063,70 +3158,23 @@ static enum ofperr handle_table_stats_request(struct ofconn *ofconn, const struct ofp_header *request) { - struct mf_bitmap rw_fields = MF_BITMAP_INITIALIZER; - struct ofproto *p = ofconn_get_ofproto(ofconn); + struct ofproto *ofproto = ofconn_get_ofproto(ofconn); + struct ofputil_table_features *features; struct ofputil_table_stats *stats; - struct ofpbuf *msg; - int n_tables; + struct ofpbuf *reply; size_t i; - for (i = 0; i < MFF_N_IDS; i++) { - if (mf_from_id(i)->writable) { - bitmap_set1(rw_fields.bm, i); - } - } - - /* Set up default values. - * - * ofp12_table_stats is used as a generic structure as - * it is able to hold all the fields for ofp10_table_stats - * and ofp11_table_stats (and of course itself). - */ - stats = xcalloc(p->n_tables, sizeof *stats); - for (i = 0; i < p->n_tables; i++) { - unsigned int config; - - stats[i].table_id = i; - sprintf(stats[i].name, "table%"PRIuSIZE, i); - bitmap_set_multiple(stats[i].match.bm, 0, MFF_N_IDS, 1); - bitmap_set_multiple(stats[i].wildcards.bm, 0, MFF_N_IDS, 1); - stats[i].write_ofpacts = (UINT64_C(1) << N_OFPACTS) - 1; - stats[i].apply_ofpacts = (UINT64_C(1) << N_OFPACTS) - 1; - stats[i].write_setfields = rw_fields; - stats[i].apply_setfields = rw_fields; - stats[i].metadata_match = OVS_BE64_MAX; - stats[i].metadata_write = OVS_BE64_MAX; - stats[i].instructions = OFPIT13_ALL; - atomic_read(&p->tables[i].config, &config); - stats[i].config = config; - stats[i].max_entries = 1000000; /* An arbitrary big number. */ - stats[i].active_count = classifier_count(&p->tables[i].cls); - } - - p->ofproto_class->get_tables(p, stats); - - /* Post-process the tables, dropping hidden tables. */ - n_tables = p->n_tables; - for (i = 0; i < p->n_tables; i++) { - const struct oftable *table = &p->tables[i]; - - if (table->flags & OFTABLE_HIDDEN) { - n_tables = i; - break; - } - - if (table->name) { - ovs_strzcpy(stats[i].name, table->name, sizeof stats[i].name); - } + query_tables(ofproto, &features, &stats); - if (table->max_flows < stats[i].max_entries) { - stats[i].max_entries = table->max_flows; + reply = ofputil_encode_table_stats_reply(request); + for (i = 0; i < ofproto->n_tables; i++) { + if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) { + ofputil_append_table_stats_reply(reply, &stats[i], &features[i]); } } + ofconn_send_reply(ofconn, reply); - msg = ofputil_encode_table_stats_reply(stats, n_tables, request); - ofconn_send_reply(ofconn, msg); - + free(features); free(stats); return 0; |