X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fcfm.c;h=b4f64c71957feb9f633259275fec355a32a71893;hb=ef9819b5f131ae3c727309a7f3758fa079679c85;hp=2a79d633396da306dfa8037cbeee5e6506ebd981;hpb=e14749faf150dc909119b5431a2cd9e779623a71;p=openvswitch diff --git a/lib/cfm.c b/lib/cfm.c index 2a79d633..b4f64c71 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -36,8 +36,13 @@ VLOG_DEFINE_THIS_MODULE(cfm); +#define CFM_MAX_RMPS 256 + /* Ethernet destination address of CCM packets. */ static const uint8_t eth_addr_ccm[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x30 }; +static const uint8_t eth_addr_ccm_x[6] = { + 0x01, 0x23, 0x20, 0x00, 0x00, 0x30 +}; #define ETH_TYPE_CFM 0x8902 @@ -65,8 +70,8 @@ struct cfm { struct hmap_node hmap_node; /* Node in all_cfms list. */ uint16_t mpid; + bool extended; /* Extended mode. */ bool fault; /* Indicates connectivity fault. */ - bool recv_fault; /* Indicates an inability to receive CCMs. */ bool unexpected_recv; /* Received an unexpected CCM. */ uint32_t seq; /* The sequence number of our last CCM. */ @@ -77,7 +82,7 @@ struct cfm { struct timer tx_timer; /* Send CCM when expired. */ struct timer fault_timer; /* Check for faults when expired. */ - struct hmap remote_mps; /* Expected remote MPs. */ + struct hmap remote_mps; /* Remote MPs. */ }; /* Remote MPs represent foreign network entities that are configured to have @@ -87,7 +92,6 @@ struct remote_mp { struct hmap_node node; /* Node in 'remote_mps' map. */ bool recv; /* CCM was received since last fault check. */ - bool fault; /* Indicates a connectivity fault. */ bool rdi; /* Remote Defect Indicator. Indicates remote_mp isn't receiving CCMs that it's expecting to. */ }; @@ -98,6 +102,12 @@ static struct hmap all_cfms = HMAP_INITIALIZER(&all_cfms); static void cfm_unixctl_show(struct unixctl_conn *, const char *args, void *aux); +static const uint8_t * +cfm_ccm_addr(const struct cfm *cfm) +{ + return cfm->extended ? eth_addr_ccm_x : eth_addr_ccm; +} + static void cfm_generate_maid(struct cfm *cfm) { @@ -183,11 +193,11 @@ cfm_is_valid_mpid(uint32_t mpid) } static struct remote_mp * -lookup_remote_mp(const struct hmap *hmap, uint16_t mpid) +lookup_remote_mp(const struct cfm *cfm, uint16_t mpid) { struct remote_mp *rmp; - HMAP_FOR_EACH_IN_BUCKET (rmp, node, hash_mpid(mpid), hmap) { + HMAP_FOR_EACH_IN_BUCKET (rmp, node, hash_mpid(mpid), &cfm->remote_mps) { if (rmp->mpid == mpid) { return rmp; } @@ -243,32 +253,37 @@ cfm_run(struct cfm *cfm) { if (timer_expired(&cfm->fault_timer)) { long long int interval = cfm_fault_interval(cfm); - struct remote_mp *rmp; + struct remote_mp *rmp, *rmp_next; cfm->fault = cfm->unexpected_recv; - cfm->recv_fault = false; cfm->unexpected_recv = false; - HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) { - rmp->fault = !rmp->recv; - rmp->recv = false; + HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfm->remote_mps) { - if (rmp->fault) { - cfm->recv_fault = true; + if (!rmp->recv) { VLOG_DBG("%s: No CCM from RMP %"PRIu16" in the last %lldms", cfm->name, rmp->mpid, interval); - } else if (rmp->rdi) { - cfm->fault = true; - VLOG_DBG("%s: RDI bit flagged from RMP %"PRIu16, cfm->name, - rmp->mpid); + hmap_remove(&cfm->remote_mps, &rmp->node); + free(rmp); + } else { + rmp->recv = false; + + if (rmp->mpid == cfm->mpid) { + VLOG_WARN_RL(&rl, "%s: Received CCM with local MPID (%d)", + cfm->name, rmp->mpid); + cfm->fault = true; + } + + if (rmp->rdi) { + VLOG_DBG("%s: RDI bit flagged from RMP %"PRIu16, cfm->name, + rmp->mpid); + cfm->fault = true; + } } } - if (cfm->recv_fault) { + if (hmap_is_empty(&cfm->remote_mps)) { cfm->fault = true; - } else { - VLOG_DBG("%s: All RMPs received CCMs in the last %lldms", - cfm->name, interval); } timer_set_duration(&cfm->fault_timer, interval); @@ -292,8 +307,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, struct ccm *ccm; timer_set_duration(&cfm->tx_timer, cfm->ccm_interval_ms); - - ccm = eth_compose(packet, eth_addr_ccm, eth_src, ETH_TYPE_CFM, + ccm = eth_compose(packet, cfm_ccm_addr(cfm), eth_src, ETH_TYPE_CFM, sizeof *ccm); ccm->mdlevel_version = 0; ccm->opcode = CCM_OPCODE; @@ -304,7 +318,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, memcpy(ccm->maid, cfm->maid, sizeof ccm->maid); memset(ccm->zero, 0, sizeof ccm->zero); - if (cfm->recv_fault) { + if (hmap_is_empty(&cfm->remote_mps)) { ccm->flags |= CCM_RDI_MASK; } } @@ -321,17 +335,14 @@ cfm_wait(struct cfm *cfm) bool cfm_configure(struct cfm *cfm, const struct cfm_settings *s) { - size_t i; uint8_t interval; - struct hmap new_rmps; - struct remote_mp *rmp, *rmp_next; - if (!cfm_is_valid_mpid(s->mpid) || s->interval <= 0 - || s->n_remote_mpids <= 0) { + if (!cfm_is_valid_mpid(s->mpid) || s->interval <= 0) { return false; } cfm->mpid = s->mpid; + cfm->extended = s->extended; interval = ms_to_ccm_interval(s->interval); if (interval != cfm->ccm_interval) { @@ -342,41 +353,15 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s) timer_set_duration(&cfm->fault_timer, cfm_fault_interval(cfm)); } - hmap_init(&new_rmps); - for (i = 0; i < s->n_remote_mpids; i++) { - uint16_t mpid = s->remote_mpids[i]; - - if (!cfm_is_valid_mpid(mpid) - || lookup_remote_mp(&new_rmps, mpid)) { - continue; - } - - if ((rmp = lookup_remote_mp(&cfm->remote_mps, mpid))) { - hmap_remove(&cfm->remote_mps, &rmp->node); - } else { - rmp = xzalloc(sizeof *rmp); - rmp->mpid = mpid; - } - - hmap_insert(&new_rmps, &rmp->node, hash_mpid(mpid)); - } - - hmap_swap(&new_rmps, &cfm->remote_mps); - HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &new_rmps) { - hmap_remove(&new_rmps, &rmp->node); - free(rmp); - } - hmap_destroy(&new_rmps); - return true; } -/* Returns true if the CFM library should process packets from 'flow'. */ +/* Returns true if 'cfm' should process packets from 'flow'. */ bool -cfm_should_process_flow(const struct flow *flow) +cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow) { return (ntohs(flow->dl_type) == ETH_TYPE_CFM - && eth_addr_equals(flow->dl_dst, eth_addr_ccm)); + && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm))); } /* Updates internal statistics relevant to packet 'p'. Should be called on @@ -425,21 +410,26 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) ccm_interval = ccm->flags & 0x7; ccm_rdi = ccm->flags & CCM_RDI_MASK; - rmp = lookup_remote_mp(&cfm->remote_mps, ccm_mpid); + if (ccm_interval != cfm->ccm_interval) { + VLOG_WARN_RL(&rl, "%s: received a CCM with an invalid interval" + " (%"PRIu8") from RMP %"PRIu16, cfm->name, + ccm_interval, ccm_mpid); + } + rmp = lookup_remote_mp(cfm, ccm_mpid); if (rmp) { rmp->recv = true; rmp->rdi = ccm_rdi; - - if (ccm_interval != cfm->ccm_interval) { - VLOG_WARN_RL(&rl, "%s: received a CCM with an invalid interval" - " (%"PRIu8") from RMP %"PRIu16, cfm->name, - ccm_interval, rmp->mpid); - } + } else if (hmap_count(&cfm->remote_mps) < CFM_MAX_RMPS) { + rmp = xmalloc(sizeof *rmp); + rmp->mpid = ccm_mpid; + rmp->recv = true; + rmp->rdi = ccm_rdi; + hmap_insert(&cfm->remote_mps, &rmp->node, hash_mpid(rmp->mpid)); } else { cfm->unexpected_recv = true; - VLOG_WARN_RL(&rl, "%s: Received unexpected remote MPID %d from" - " MAC " ETH_ADDR_FMT, cfm->name, ccm_mpid, + VLOG_WARN_RL(&rl, "%s: dropped CCM with MPID %d from MAC " + ETH_ADDR_FMT, cfm->name, ccm_mpid, ETH_ADDR_ARGS(eth->eth_src)); } @@ -484,10 +474,9 @@ cfm_unixctl_show(struct unixctl_conn *conn, return; } - ds_put_format(&ds, "MPID %"PRIu16":%s%s%s\n", cfm->mpid, + ds_put_format(&ds, "MPID %"PRIu16":%s%s\n", cfm->mpid, cfm->fault ? " fault" : "", - cfm->unexpected_recv ? " unexpected_recv" : "", - cfm->recv_fault ? " recv_fault" : ""); + cfm->unexpected_recv ? " unexpected_recv" : ""); ds_put_format(&ds, "\tinterval: %dms\n", cfm->ccm_interval_ms); ds_put_format(&ds, "\tnext CCM tx: %lldms\n", @@ -497,8 +486,8 @@ cfm_unixctl_show(struct unixctl_conn *conn, ds_put_cstr(&ds, "\n"); HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) { - ds_put_format(&ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid, - rmp->fault ? "fault" : ""); + ds_put_format(&ds, "Remote MPID %"PRIu16":%s\n", rmp->mpid, + rmp->rdi ? " rdi" : ""); ds_put_format(&ds, "\trecv since check: %s", rmp->recv ? "true" : "false"); }