X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=cb46d26df5e4e4fd2d547417be6617e24c2616aa;hb=25b257179790c4dc21564e0652a525c2641e144f;hp=aa97124f49f99e85fc300d0aa70b07742bdc196a;hpb=05fe17646fc1ed2527f26eddb13e09ec14cc29b9;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index aa97124f4..cb46d26df 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1027,8 +1027,9 @@ process_port_change(struct ofproto *ofproto, int error, char *devname) int ofproto_run(struct ofproto *p) { + struct sset changed_netdevs; + const char *changed_netdev; struct ofport *ofport; - char *devname; int error; error = p->ofproto_class->run(p); @@ -1037,18 +1038,31 @@ ofproto_run(struct ofproto *p) } if (p->ofproto_class->port_poll) { + char *devname; + while ((error = p->ofproto_class->port_poll(p, &devname)) != EAGAIN) { process_port_change(p, error, devname); } } + /* Update OpenFlow port status for any port whose netdev has changed. + * + * Refreshing a given 'ofport' can cause an arbitrary ofport to be + * destroyed, so it's not safe to update ports directly from the + * HMAP_FOR_EACH loop, or even to use HMAP_FOR_EACH_SAFE. Instead, we + * need this two-phase approach. */ + sset_init(&changed_netdevs); HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { unsigned int change_seq = netdev_change_seq(ofport->netdev); if (ofport->change_seq != change_seq) { ofport->change_seq = change_seq; - update_port(p, netdev_get_name(ofport->netdev)); + sset_add(&changed_netdevs, netdev_get_name(ofport->netdev)); } } + SSET_FOR_EACH (changed_netdev, &changed_netdevs) { + update_port(p, changed_netdev); + } + sset_destroy(&changed_netdevs); switch (p->state) { case S_OPENFLOW: @@ -2481,6 +2495,19 @@ ofproto_port_get_cfm_remote_mpids(const struct ofproto *ofproto, : -1); } +/* Checks the health of the CFM for 'ofp_port' within 'ofproto'. Returns an + * integer value between 0 and 100 to indicate the health of the port as a + * percentage which is the average of cfm health of all the remote_mpids or + * returns -1 if CFM is not enabled on 'ofport'. */ +int +ofproto_port_get_cfm_health(const struct ofproto *ofproto, uint16_t ofp_port) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + return (ofport && ofproto->ofproto_class->get_cfm_health + ? ofproto->ofproto_class->get_cfm_health(ofport) + : -1); +} + static enum ofperr handle_aggregate_stats_request(struct ofconn *ofconn, const struct ofp_stats_msg *osm) @@ -3064,7 +3091,7 @@ handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh) role = ntohl(nrr->role); if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER && role != NX_ROLE_SLAVE) { - return OFPERR_NXBRC_BAD_ROLE; + return OFPERR_OFPRRFC_BAD_ROLE; } if (ofconn_get_role(ofconn) != role