Ports with unknown MACs are a per-lswitch concept but the code here was treating them as global and also dereferenced a null pointer (generally 'lport' was null in the expression 'lswitch->lport').
Reported-by: Alex Wang <al...@nicira.com> Signed-off-by: Ben Pfaff <b...@nicira.com> --- ovn/northd/ovn-northd.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 8a09ce1..60ae608 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -359,8 +359,14 @@ build_pipeline(struct northd_context *ctx) } /* Table 1: Destination lookup, unicast handling (priority 50), */ - struct ds unknown_actions = DS_EMPTY_INITIALIZER; + struct unknown_actions { + struct hmap_node hmap_node; + const struct nbrec_logical_switch *ls; + struct ds actions; + }; + struct hmap unknown_actions = HMAP_INITIALIZER(&unknown_actions); NBREC_LOGICAL_PORT_FOR_EACH (lport, ctx->ovnnb_idl) { + lswitch = lport->lswitch; for (size_t i = 0; i < lport->n_macs; i++) { uint8_t mac[ETH_ADDR_LEN]; @@ -374,14 +380,33 @@ build_pipeline(struct northd_context *ctx) ds_put_cstr(&actions, "outport = "); json_string_escape(lport->name, &actions); ds_put_cstr(&actions, "; resubmit;"); - pipeline_add(&pc, lport->lswitch, 1, 50, + pipeline_add(&pc, lswitch, 1, 50, ds_cstr(&match), ds_cstr(&actions)); ds_destroy(&actions); ds_destroy(&match); } else if (!strcmp(lport->macs[i], "unknown")) { - ds_put_cstr(&unknown_actions, "outport = "); - json_string_escape(lport->name, &unknown_actions); - ds_put_cstr(&unknown_actions, "; resubmit; "); + const struct uuid *uuid = &lswitch->header_.uuid; + struct unknown_actions *ua = NULL; + struct unknown_actions *iter; + HMAP_FOR_EACH_WITH_HASH (iter, hmap_node, uuid_hash(uuid), + &unknown_actions) { + if (uuid_equals(&iter->ls->header_.uuid, uuid)) { + ua = iter; + break; + } + } + if (!ua) { + ua = xmalloc(sizeof *ua); + ua->ls = lswitch; + ds_init(&ua->actions); + } else { + ds_put_char(&ua->actions, ' '); + } + + struct ds s = DS_EMPTY_INITIALIZER; + ds_put_cstr(&s, "outport = "); + json_string_escape(lport->name, &s); + ds_put_cstr(&s, "; resubmit;"); } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); @@ -392,12 +417,14 @@ build_pipeline(struct northd_context *ctx) } /* Table 1: Destination lookup for unknown MACs (priority 0). */ - if (unknown_actions.length) { - ds_chomp(&unknown_actions, ' '); - pipeline_add(&pc, lport->lswitch, 1, 0, "1", - ds_cstr(&unknown_actions)); + struct unknown_actions *ua, *next_ua; + HMAP_FOR_EACH_SAFE (ua, next_ua, hmap_node, &unknown_actions) { + pipeline_add(&pc, ua->ls, 1, 0, "1", ds_cstr(&ua->actions)); + hmap_remove(&unknown_actions, &ua->hmap_node); + ds_destroy(&ua->actions); + free(ua); } - ds_destroy(&unknown_actions); + hmap_destroy(&unknown_actions); /* Table 2: ACLs. */ const struct nbrec_acl *acl; -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev