cfm: Migrate cfm/show unixctl command to CFM module.
authorEthan Jackson <ethan@nicira.com>
Fri, 13 May 2011 23:53:24 +0000 (16:53 -0700)
committerEthan Jackson <ethan@nicira.com>
Fri, 20 May 2011 22:53:28 +0000 (15:53 -0700)
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.

lib/cfm.c
lib/cfm.h
ofproto/ofproto-dpif.c
vswitchd/bridge.c

index a605c09..ff416a3 100644 (file)
--- 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);
 }
index 4bb8dc9..c83a7cc 100644 (file)
--- 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 */
index d3cb92b..5807c56 100644 (file)
@@ -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);
index ec4bb7b..aba0b94 100644 (file)
@@ -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)
     }
 }
 \f
-/* 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);
-}
-\f
 /* 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);