summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEthan Jackson <ethan@nicira.com>2011-05-13 16:53:24 -0700
committerEthan Jackson <ethan@nicira.com>2011-05-20 15:53:28 -0700
commit9ac3fce4d5aea7e963439eb97f7c2d157aef4dfc (patch)
tree79e3beaeca613b5b46f9e3a81e6757cd5fa05d76
parentc8544aa15f8811e9d6329d4a5e612ff7acb926c9 (diff)
downloadopenvswitch-9ac3fce4d5aea7e963439eb97f7c2d157aef4dfc.tar.gz
cfm: Migrate cfm/show unixctl command to CFM module.
This patch moves the cfm/show unixctl show command from the bridge to the CFM module. This is more in line with how LACP does it, and will make future patches easier to implement.
-rw-r--r--lib/cfm.c64
-rw-r--r--lib/cfm.h9
-rw-r--r--ofproto/ofproto-dpif.c1
-rw-r--r--vswitchd/bridge.c31
4 files changed, 58 insertions, 47 deletions
diff --git a/lib/cfm.c b/lib/cfm.c
index a605c098e..ff416a357 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -30,6 +30,7 @@
#include "poll-loop.h"
#include "timer.h"
#include "timeval.h"
+#include "unixctl.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(cfm);
@@ -38,8 +39,9 @@ VLOG_DEFINE_THIS_MODULE(cfm);
struct cfm_internal {
struct cfm cfm;
- uint32_t seq; /* The sequence number of our last CCM. */
+ struct list list_node; /* Node in all_cfms list. */
+ uint32_t seq; /* The sequence number of our last CCM. */
uint8_t ccm_interval; /* The CCM transmission interval. */
int ccm_interval_ms; /* 'ccm_interval' in milliseconds. */
@@ -48,6 +50,10 @@ struct cfm_internal {
};
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+static struct list all_cfms = LIST_INITIALIZER(&all_cfms);
+
+static void cfm_unixctl_show(struct unixctl_conn *, const char *args,
+ void *aux);
static int
ccm_interval_to_ms(uint8_t interval)
@@ -128,6 +134,12 @@ lookup_remote_mp(const struct hmap *hmap, uint16_t mpid)
return NULL;
}
+void
+cfm_init(void)
+{
+ unixctl_command_register("cfm/show", cfm_unixctl_show, NULL);
+}
+
/* Allocates a 'cfm' object. This object should have its 'mpid', 'maid',
* 'eth_src', and 'interval' filled out. cfm_configure() should be called
* whenever changes are made to 'cfm', and before cfm_run() is called for the
@@ -142,6 +154,7 @@ cfm_create(void)
cfm = &cfmi->cfm;
hmap_init(&cfm->remote_mps);
+ list_push_back(&all_cfms, &cfmi->list_node);
return cfm;
}
@@ -161,6 +174,7 @@ cfm_destroy(struct cfm *cfm)
}
hmap_destroy(&cfm->remote_mps);
+ list_remove(&cfmi->list_node);
free(cfmi);
}
@@ -411,26 +425,50 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
}
}
-void
-cfm_dump_ds(const struct cfm *cfm, struct ds *ds)
+static struct cfm_internal *
+cfm_find(const char *name)
{
- const struct cfm_internal *cfmi = cfm_to_internal(cfm);
+ struct cfm_internal *cfmi;
+
+ LIST_FOR_EACH (cfmi, list_node, &all_cfms) {
+ if (cfmi->cfm.name && !strcmp(cfmi->cfm.name, name)) {
+ return cfmi;
+ }
+ }
+ return NULL;
+}
+
+static void
+cfm_unixctl_show(struct unixctl_conn *conn,
+ const char *args, void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ const struct cfm_internal *cfmi;
struct remote_mp *rmp;
- ds_put_format(ds, "MPID %"PRIu16": %s\n", cfm->mpid,
- cfm->fault ? "fault" : "");
+ cfmi = cfm_find(args);
+ if (!cfmi) {
+ unixctl_command_reply(conn, 501, "no such CFM object");
+ return;
+ }
- ds_put_format(ds, "\tinterval: %dms\n", cfmi->ccm_interval_ms);
- ds_put_format(ds, "\tnext CCM tx: %lldms\n",
+ ds_put_format(&ds, "MPID %"PRIu16": %s\n", cfmi->cfm.mpid,
+ cfmi->cfm.fault ? "fault" : "");
+
+ ds_put_format(&ds, "\tinterval: %dms\n", cfmi->ccm_interval_ms);
+ ds_put_format(&ds, "\tnext CCM tx: %lldms\n",
timer_msecs_until_expired(&cfmi->tx_timer));
- ds_put_format(ds, "\tnext fault check: %lldms\n",
+ ds_put_format(&ds, "\tnext fault check: %lldms\n",
timer_msecs_until_expired(&cfmi->fault_timer));
- ds_put_cstr(ds, "\n");
- HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
- ds_put_format(ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid,
+ ds_put_cstr(&ds, "\n");
+ HMAP_FOR_EACH (rmp, node, &cfmi->cfm.remote_mps) {
+ ds_put_format(&ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid,
rmp->fault ? "fault" : "");
- ds_put_format(ds, "\trecv since check: %s",
+ ds_put_format(&ds, "\trecv since check: %s",
rmp->recv ? "true" : "false");
}
+
+ unixctl_command_reply(conn, 200, ds_cstr(&ds));
+ ds_destroy(&ds);
}
diff --git a/lib/cfm.h b/lib/cfm.h
index 4bb8dc93e..c83a7cce1 100644
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -1,5 +1,4 @@
-/*
- * Copyright (c) 2010 Nicira Networks.
+/* Copyright (c) 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +23,6 @@
struct flow;
struct ofpbuf;
-struct ds;
/* Ethernet destination address of CCM packets. */
static const uint8_t eth_addr_ccm[6] OVS_UNUSED
@@ -57,6 +55,7 @@ struct cfm {
uint16_t mpid; /* The MPID of this CFM. */
uint8_t maid[CCM_MAID_LEN]; /* The MAID of this CFM. */
int interval; /* The requested transmission interval. */
+ const char *name; /* Name of this CFM object. */
/* Statistics. */
struct hmap remote_mps; /* Expected remote MPs. */
@@ -73,6 +72,8 @@ struct remote_mp {
bool fault; /* Indicates a connectivity fault. */
};
+void cfm_init(void);
+
struct cfm *cfm_create(void);
void cfm_destroy(struct cfm *);
@@ -98,6 +99,4 @@ bool cfm_should_process_flow(const struct flow *);
void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet);
-void cfm_dump_ds(const struct cfm *, struct ds *);
-
#endif /* cfm.h */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d3cb92b91..5807c5647 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -750,6 +750,7 @@ set_cfm(struct ofport *ofport_, const struct cfm *cfm,
ofport->cfm->mpid = cfm->mpid;
ofport->cfm->interval = cfm->interval;
+ ofport->cfm->name = cfm->name;
memcpy(ofport->cfm->maid, cfm->maid, CCM_MAID_LEN);
cfm_update_remote_mps(ofport->cfm, remote_mps, n_remote_mps);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index ec4bb7bef..aba0b942e 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -164,7 +164,6 @@ static bool bridge_has_bond_fake_iface(const struct bridge *,
const char *name);
static bool port_is_bond_fake_iface(const struct port *);
-static unixctl_cb_func cfm_unixctl_show;
static unixctl_cb_func qos_unixctl_show;
static struct port *port_create(struct bridge *, const struct ovsrec_port *);
@@ -268,7 +267,6 @@ bridge_init(const char *remote)
ovsdb_idl_omit(idl, &ovsrec_ssl_col_external_ids);
/* Register unixctl commands. */
- unixctl_command_register("cfm/show", cfm_unixctl_show, NULL);
unixctl_command_register("qos/show", qos_unixctl_show, NULL);
unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
NULL);
@@ -276,6 +274,7 @@ bridge_init(const char *remote)
NULL);
lacp_init();
bond_init();
+ cfm_init();
}
void
@@ -1501,33 +1500,6 @@ bridge_wait(void)
}
}
-/* CFM unixctl user interface functions. */
-static void
-cfm_unixctl_show(struct unixctl_conn *conn,
- const char *args, void *aux OVS_UNUSED)
-{
- struct ds ds = DS_EMPTY_INITIALIZER;
- struct iface *iface;
- const struct cfm *cfm;
-
- iface = iface_find(args);
- if (!iface) {
- unixctl_command_reply(conn, 501, "no such interface");
- return;
- }
-
- cfm = ofproto_port_get_cfm(iface->port->bridge->ofproto, iface->ofp_port);
-
- if (!cfm) {
- unixctl_command_reply(conn, 501, "CFM not enabled");
- return;
- }
-
- cfm_dump_ds(cfm, &ds);
- unixctl_command_reply(conn, 200, ds_cstr(&ds));
- ds_destroy(&ds);
-}
-
/* QoS unixctl user interface functions. */
struct qos_unixctl_show_cbdata {
@@ -2549,6 +2521,7 @@ iface_configure_cfm(struct iface *iface)
cfm.mpid = mon->mpid;
cfm.interval = mon->interval ? *mon->interval : 1000;
+ cfm.name = iface->name;
memcpy(cfm.maid, maid, sizeof cfm.maid);