From: Dennis Flynn <[email protected]>
Signed-off-by: Ludovic Beliveau <[email protected]>
Signed-off-by: Dennis Flynn <[email protected]>
diff --git a/lib/bfd.c b/lib/bfd.c
index 3db1d57..490dbd0 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -515,10 +515,12 @@ bfd_unref(struct bfd *bfd) OVS_EXCLUDED(mutex)
}
}
-void
+long long int
bfd_wait(const struct bfd *bfd) OVS_EXCLUDED(mutex)
{
- poll_timer_wait_until(bfd_wake_time(bfd));
+ long long int wake_time = bfd_wake_time(bfd);
+ poll_timer_wait_until(wake_time);
+ return wake_time;
}
/* Returns the next wake up time. */
diff --git a/lib/bfd.h b/lib/bfd.h
index d803bf9..a02521b 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -31,7 +31,7 @@ struct netdev;
struct ofpbuf;
struct smap;
-void bfd_wait(const struct bfd *);
+long long int bfd_wait(const struct bfd *);
void bfd_run(struct bfd *);
bool bfd_should_send_packet(const struct bfd *);
diff --git a/lib/cfm.c b/lib/cfm.c
index 23c1c6f..58a8852 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -629,10 +629,12 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet,
ovs_mutex_unlock(&mutex);
}
-void
+long long int
cfm_wait(struct cfm *cfm) OVS_EXCLUDED(mutex)
{
- poll_timer_wait_until(cfm_wake_time(cfm));
+ long long int wake_time = cfm_wake_time(cfm);
+ poll_timer_wait_until(wake_time);
+ return wake_time;
}
diff --git a/lib/cfm.h b/lib/cfm.h
index b3a2d45..ca6d015 100644
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -94,7 +94,7 @@ void cfm_unref(struct cfm *);
void cfm_run(struct cfm *);
bool cfm_should_send_ccm(struct cfm *);
void cfm_compose_ccm(struct cfm *, struct ofpbuf *packet, uint8_t
eth_src[ETH_ADDR_LEN]);
-void cfm_wait(struct cfm *);
+long long int cfm_wait(struct cfm *);
bool cfm_configure(struct cfm *, const struct cfm_settings *);
void cfm_set_netdev(struct cfm *, const struct netdev *);
bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *,
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 178fa11..d693e02 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -40,6 +40,7 @@ struct pkt_metadata;
SPR(SLOW_BFD, "bfd", "Consists of BFD packets") \
SPR(SLOW_LACP, "lacp", "Consists of LACP packets") \
SPR(SLOW_STP, "stp", "Consists of STP packets") \
+ SPR(SLOW_LLDP, "lldp", "Consists of LLDP packets") \
SPR(SLOW_CONTROLLER, "controller", \
"Sends \"packet-in\" messages to the OpenFlow controller") \
SPR(SLOW_ACTION, "action", \
diff --git a/ofproto/ofproto-dpif-monitor.c b/ofproto/ofproto-dpif-monitor.c
index 14de027..37293cb 100644
--- a/ofproto/ofproto-dpif-monitor.c
+++ b/ofproto/ofproto-dpif-monitor.c
@@ -28,6 +28,7 @@
#include "latch.h"
#include "ofpbuf.h"
#include "ofproto-dpif.h"
+#include "ovs-lldp.h"
#include "ovs-thread.h"
#include "poll-loop.h"
#include "seq.h"
@@ -42,7 +43,7 @@ VLOG_DEFINE_THIS_MODULE(ofproto_dpif_monitor);
/* Converts the heap priority to time in millisecond. */
#define PRIO_TO_MSEC(PRIO) (LLONG_MAX - (PRIO))
-/* Monitored port. It owns references to ofport, bfd, cfm structs. */
+/* Monitored port. It owns references to ofport, bfd, cfm, and lldp structs.
*/
struct mport {
struct hmap_node hmap_node; /* In monitor_hmap. */
struct heap_node heap_node; /* In monitor_heap. */
@@ -50,6 +51,7 @@ struct mport {
struct cfm *cfm; /* Reference to cfm. */
struct bfd *bfd; /* Reference to bfd. */
+ struct lldp *lldp; /* Reference to lldp. */
uint8_t hw_addr[OFP_ETH_ALEN]; /* Hardware address. */
};
@@ -85,12 +87,13 @@ static void monitor_run(void);
static void monitor_mport_run(struct mport *, struct ofpbuf *);
static void mport_register(const struct ofport_dpif *, struct bfd *,
- struct cfm *, uint8_t[ETH_ADDR_LEN])
+ struct cfm *, struct lldp *, uint8_t[ETH_ADDR_LEN])
OVS_REQUIRES(monitor_mutex);
static void mport_unregister(const struct ofport_dpif *)
OVS_REQUIRES(monitor_mutex);
static void mport_update(struct mport *, struct bfd *, struct cfm *,
- uint8_t[ETH_ADDR_LEN]) OVS_REQUIRES(monitor_mutex);
+ struct lldp *, uint8_t[ETH_ADDR_LEN])
+ OVS_REQUIRES(monitor_mutex);
static struct mport *mport_find(const struct ofport_dpif *)
OVS_REQUIRES(monitor_mutex);
@@ -114,7 +117,7 @@ mport_find(const struct ofport_dpif *ofport)
OVS_REQUIRES(monitor_mutex)
* if it doesn't exist. Otherwise, just updates its fields. */
static void
mport_register(const struct ofport_dpif *ofport, struct bfd *bfd,
- struct cfm *cfm, uint8_t *hw_addr)
+ struct cfm *cfm, struct lldp *lldp, uint8_t *hw_addr)
OVS_REQUIRES(monitor_mutex)
{
struct mport *mport = mport_find(ofport);
@@ -125,7 +128,7 @@ mport_register(const struct ofport_dpif *ofport, struct bfd
*bfd,
hmap_insert(&monitor_hmap, &mport->hmap_node, hash_pointer(ofport, 0));
heap_insert(&monitor_heap, &mport->heap_node, 0);
}
- mport_update(mport, bfd, cfm, hw_addr);
+ mport_update(mport, bfd, cfm, lldp, hw_addr);
}
/* Removes mport from monitor_hmap and monitor_heap and frees it. */
@@ -136,7 +139,7 @@ mport_unregister(const struct ofport_dpif *ofport)
struct mport *mport = mport_find(ofport);
if (mport) {
- mport_update(mport, NULL, NULL, NULL);
+ mport_update(mport, NULL, NULL, NULL, NULL);
hmap_remove(&monitor_hmap, &mport->hmap_node);
heap_remove(&monitor_heap, &mport->heap_node);
free(mport);
@@ -146,7 +149,8 @@ mport_unregister(const struct ofport_dpif *ofport)
/* Updates the fields of an existing mport struct. */
static void
mport_update(struct mport *mport, struct bfd *bfd, struct cfm *cfm,
- uint8_t hw_addr[ETH_ADDR_LEN]) OVS_REQUIRES(monitor_mutex)
+ struct lldp *lldp, uint8_t hw_addr[ETH_ADDR_LEN])
+ OVS_REQUIRES(monitor_mutex)
{
ovs_assert(mport);
@@ -158,12 +162,16 @@ mport_update(struct mport *mport, struct bfd *bfd, struct
cfm *cfm,
bfd_unref(mport->bfd);
mport->bfd = bfd_ref(bfd);
}
+ if (mport->lldp != lldp) {
+ lldp_unref(mport->lldp);
+ mport->lldp = lldp_ref(lldp);
+ }
if (hw_addr && memcmp(mport->hw_addr, hw_addr, ETH_ADDR_LEN)) {
memcpy(mport->hw_addr, hw_addr, ETH_ADDR_LEN);
}
- /* If bfd/cfm is added or reconfigured, move the mport on top of the heap
+ /* If bfd/cfm/lldp is added or reconfigured, move the mport on top of the
heap
* so that the monitor thread can run the mport next time it wakes up. */
- if (mport->bfd || mport->cfm) {
+ if (mport->bfd || mport->cfm || mport->lldp) {
heap_change(&monitor_heap, &mport->heap_node, LLONG_MAX);
}
}
@@ -259,6 +267,9 @@ monitor_mport_run(struct mport *mport, struct ofpbuf
*packet)
OVS_REQUIRES(monitor_mutex)
{
long long int next_wake_time;
+ long long int bfd_wake_time = LLONG_MAX;
+ long long int cfm_wake_time = LLONG_MAX;
+ long long int lldp_wake_time = LLONG_MAX;
if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
ofpbuf_clear(packet);
@@ -270,17 +281,27 @@ monitor_mport_run(struct mport *mport, struct ofpbuf
*packet)
bfd_put_packet(mport->bfd, packet, mport->hw_addr);
ofproto_dpif_send_packet(mport->ofport, packet);
}
+ if (mport->lldp && lldp_should_send_packet(mport->lldp)) {
+ ofpbuf_clear(packet);
+ lldp_put_packet(mport->lldp, packet, mport->hw_addr);
+ ofproto_dpif_send_packet(mport->ofport, packet);
+ }
+
if (mport->cfm) {
cfm_run(mport->cfm);
- cfm_wait(mport->cfm);
+ cfm_wake_time = cfm_wait(mport->cfm);
}
if (mport->bfd) {
bfd_run(mport->bfd);
- bfd_wait(mport->bfd);
+ bfd_wake_time = bfd_wait(mport->bfd);
+ }
+ if (mport->lldp) {
+ lldp_wake_time = lldp_wait(mport->lldp);
}
/* Computes the next wakeup time for this mport. */
- next_wake_time = MIN(bfd_wake_time(mport->bfd),
- cfm_wake_time(mport->cfm));
+ next_wake_time = MIN(bfd_wake_time,
+ cfm_wake_time);
+ next_wake_time = MIN(next_wake_time, lldp_wake_time);
heap_change(&monitor_heap, &mport->heap_node,
MSEC_TO_PRIO(next_wake_time));
}
@@ -293,13 +314,14 @@ monitor_mport_run(struct mport *mport, struct ofpbuf
*packet)
void
ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport,
struct bfd *bfd, struct cfm *cfm,
+ struct lldp *lldp,
uint8_t hw_addr[ETH_ADDR_LEN])
{
ovs_mutex_lock(&monitor_mutex);
- if (!cfm && !bfd) {
+ if (!cfm && !bfd && !lldp) {
mport_unregister(ofport);
} else {
- mport_register(ofport, bfd, cfm, hw_addr);
+ mport_register(ofport, bfd, cfm, lldp, hw_addr);
}
ovs_mutex_unlock(&monitor_mutex);
diff --git a/ofproto/ofproto-dpif-monitor.h b/ofproto/ofproto-dpif-monitor.h
index 2c466c2..b65d70b 100644
--- a/ofproto/ofproto-dpif-monitor.h
+++ b/ofproto/ofproto-dpif-monitor.h
@@ -22,12 +22,13 @@
struct bfd;
struct cfm;
+struct lldp;
struct ofport_dpif;
void ofproto_dpif_monitor_port_send_soon(const struct ofport_dpif *);
void ofproto_dpif_monitor_port_update(const struct ofport_dpif *,
struct bfd *, struct cfm *,
- uint8_t[OFP_ETH_ALEN]);
+ struct lldp *, uint8_t[OFP_ETH_ALEN]);
#endif /* ofproto-dpif-monitor.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 0786513..a7cb991 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -37,6 +37,7 @@
#include "lacp.h"
#include "learn.h"
#include "list.h"
+#include "ovs-lldp.h"
#include "mac-learning.h"
#include "mcast-snooping.h"
#include "meta-flow.h"
@@ -165,6 +166,7 @@ struct xport {
struct cfm *cfm; /* CFM handle or null. */
struct bfd *bfd; /* BFD handle or null. */
+ struct lldp *lldp; /* LLDP handle or null. */
};
struct xlate_ctx {
@@ -387,8 +389,8 @@ static void xlate_xbundle_set(struct xbundle *xbundle,
bool floodable);
static void xlate_xport_set(struct xport *xport, odp_port_t odp_port,
const struct netdev *netdev, const struct cfm *cfm,
- const struct bfd *bfd, int stp_port_no,
- const struct rstp_port *rstp_port,
+ const struct bfd *bfd, const struct lldp *lldp,
+ int stp_port_no, const struct rstp_port *rstp_port,
enum ofputil_port_config config,
enum ofputil_port_state state, bool is_tunnel,
bool may_enable);
@@ -530,7 +532,7 @@ xlate_xbundle_set(struct xbundle *xbundle,
static void
xlate_xport_set(struct xport *xport, odp_port_t odp_port,
const struct netdev *netdev, const struct cfm *cfm,
- const struct bfd *bfd, int stp_port_no,
+ const struct bfd *bfd, const struct lldp *lldp, int
stp_port_no,
const struct rstp_port* rstp_port,
enum ofputil_port_config config, enum ofputil_port_state state,
bool is_tunnel, bool may_enable)
@@ -557,6 +559,11 @@ xlate_xport_set(struct xport *xport, odp_port_t odp_port,
xport->bfd = bfd_ref(bfd);
}
+ if (xport->lldp != lldp) {
+ lldp_unref(xport->lldp);
+ xport->lldp = lldp_ref(lldp);
+ }
+
if (xport->netdev != netdev) {
netdev_close(xport->netdev);
xport->netdev = netdev_ref(netdev);
@@ -624,9 +631,9 @@ xlate_xport_copy(struct xbridge *xbridge, struct xbundle
*xbundle,
xlate_xport_init(new_xcfg, new_xport);
xlate_xport_set(new_xport, xport->odp_port, xport->netdev, xport->cfm,
- xport->bfd, xport->stp_port_no, xport->rstp_port,
- xport->config, xport->state, xport->is_tunnel,
- xport->may_enable);
+ xport->bfd, xport->lldp, xport->stp_port_no,
+ xport->rstp_port, xport->config, xport->state,
+ xport->is_tunnel, xport->may_enable);
if (xport->peer) {
struct xport *peer = xport_lookup(new_xcfg, xport->peer->ofport);
@@ -863,8 +870,8 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct
ofbundle *ofbundle,
struct ofport_dpif *ofport, ofp_port_t ofp_port,
odp_port_t odp_port, const struct netdev *netdev,
const struct cfm *cfm, const struct bfd *bfd,
- struct ofport_dpif *peer, int stp_port_no,
- const struct rstp_port *rstp_port,
+ const struct lldp *lldp, struct ofport_dpif *peer,
+ int stp_port_no, const struct rstp_port *rstp_port,
const struct ofproto_port_queue *qdscp_list, size_t n_qdscp,
enum ofputil_port_config config,
enum ofputil_port_state state, bool is_tunnel,
@@ -887,8 +894,9 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct
ofbundle *ofbundle,
ovs_assert(xport->ofp_port == ofp_port);
- xlate_xport_set(xport, odp_port, netdev, cfm, bfd, stp_port_no,
- rstp_port, config, state, is_tunnel, may_enable);
+ xlate_xport_set(xport, odp_port, netdev, cfm, bfd, lldp,
+ stp_port_no, rstp_port, config, state, is_tunnel,
+ may_enable);
if (xport->peer) {
xport->peer->peer = NULL;
@@ -950,6 +958,7 @@ xlate_xport_remove(struct xlate_cfg *xcfg, struct xport
*xport)
rstp_port_unref(xport->rstp_port);
cfm_unref(xport->cfm);
bfd_unref(xport->bfd);
+ lldp_unref(xport->lldp);
free(xport);
}
@@ -2494,6 +2503,11 @@ process_special(struct xlate_ctx *ctx, const struct flow
*flow,
: rstp_process_packet(xport, packet);
}
return SLOW_STP;
+ } else if (xport->lldp && lldp_should_process_flow(flow)) {
+ if (packet) {
+ lldp_process_packet(xport->lldp, packet);
+ }
+ return SLOW_LLDP;
} else {
return 0;
}
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 9a03782..f8d57a3 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -23,6 +23,7 @@
#include "ofproto-dpif.h"
#include "ofproto.h"
#include "stp.h"
+#include "ovs-lldp.h"
struct bfd;
struct bond;
@@ -164,10 +165,9 @@ void xlate_bundle_remove(struct ofbundle *);
void xlate_ofport_set(struct ofproto_dpif *, struct ofbundle *,
struct ofport_dpif *, ofp_port_t, odp_port_t,
- const struct netdev *, const struct cfm *,
- const struct bfd *, struct ofport_dpif *peer,
- int stp_port_no,
- const struct rstp_port *rstp_port,
+ const struct netdev *, const struct cfm *, const struct
bfd *,
+ const struct lldp *, struct ofport_dpif *peer,
+ int stp_port_no, const struct rstp_port *rstp_port,
const struct ofproto_port_queue *qdscp,
size_t n_qdscp, enum ofputil_port_config,
enum ofputil_port_state, bool is_tunnel,
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index bf15d04..37d7ff1 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -29,6 +29,7 @@
#include "connmgr.h"
#include "coverage.h"
#include "cfm.h"
+#include "ovs-lldp.h"
#include "dpif.h"
#include "dynamic-string.h"
#include "fail-open.h"
@@ -162,6 +163,7 @@ struct ofport_dpif {
struct ovs_list bundle_node;/* In struct ofbundle's "ports" list. */
struct cfm *cfm; /* Connectivity Fault Management, if any. */
struct bfd *bfd; /* BFD, if any. */
+ struct lldp *lldp; /* lldp, if any. */
bool may_enable; /* May be enabled in bonds. */
bool is_tunnel; /* This port is a tunnel. */
bool is_layer3; /* This is a layer 3 port. */
@@ -223,6 +225,7 @@ ofport_dpif_cast(const struct ofport *ofport)
static void port_run(struct ofport_dpif *);
static int set_bfd(struct ofport *, const struct smap *);
static int set_cfm(struct ofport *, const struct cfm_settings *);
+static int set_lldp(struct ofport *ofport_, const struct smap *cfg);
static void ofport_update_peer(struct ofport_dpif *);
/* Reasons that we might need to revalidate every datapath flow, and
@@ -674,8 +677,8 @@ type_run(const char *type)
: -1;
xlate_ofport_set(ofproto, ofport->bundle, ofport,
ofport->up.ofp_port, ofport->odp_port,
- ofport->up.netdev, ofport->cfm,
- ofport->bfd, ofport->peer, stp_port,
+ ofport->up.netdev, ofport->cfm, ofport->bfd,
+ ofport->lldp, ofport->peer, stp_port,
ofport->rstp_port, ofport->qdscp,
ofport->n_qdscp, ofport->up.pp.config,
ofport->up.pp.state, ofport->is_tunnel,
@@ -1703,6 +1706,7 @@ port_construct(struct ofport *port_)
port->bundle = NULL;
port->cfm = NULL;
port->bfd = NULL;
+ port->lldp = NULL;
port->may_enable = false;
port->stp_port = NULL;
port->stp_state = STP_DISABLED;
@@ -1719,10 +1723,10 @@ port_construct(struct ofport *port_)
if (netdev_vport_is_patch(netdev)) {
/* By bailing out here, we don't submit the port to the sFlow module
- * to be considered for counter polling export. This is correct
- * because the patch port represents an interface that sFlow considers
- * to be "internal" to the switch as a whole, and therefore not an
- * candidate for counter polling. */
+ * to be considered for counter polling export. This is correct
+ * because the patch port represents an interface that sFlow considers
+ * to be "internal" to the switch as a whole, and therefore not an
+ * candidate for counter polling. */
port->odp_port = ODPP_NONE;
ofport_update_peer(port);
return 0;
@@ -1821,6 +1825,7 @@ port_destruct(struct ofport *port_)
bundle_remove(port_);
set_cfm(port_, NULL);
set_bfd(port_, NULL);
+ set_lldp(port_, NULL);
if (port->stp_port) {
stp_port_disable(port->stp_port);
}
@@ -1852,7 +1857,7 @@ port_modified(struct ofport *port_)
}
ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
- port->up.pp.hw_addr);
+ port->lldp, port->up.pp.hw_addr);
netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
@@ -1983,7 +1988,7 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings
*s)
ofport->cfm = NULL;
out:
ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
- ofport->up.pp.hw_addr);
+ ofport->lldp, ofport->up.pp.hw_addr);
return error;
}
@@ -2025,7 +2030,7 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
ofproto->backer->need_revalidate = REV_RECONFIGURE;
}
ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
- ofport->up.pp.hw_addr);
+ ofport->lldp, ofport->up.pp.hw_addr);
return 0;
}
@@ -2051,6 +2056,82 @@ get_bfd_status(struct ofport *ofport_, struct smap *smap)
return ret;
}
+
+static int
+set_lldp(struct ofport *ofport_,
+ const struct smap *cfg)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ int error = 0;
+
+ if (cfg) {
+ if (!ofport->lldp) {
+ struct ofproto_dpif *ofproto;
+
+ ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+ ofproto->backer->need_revalidate = REV_RECONFIGURE;
+ ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
+ }
+
+ if (lldp_configure(ofport->lldp)) {
+ error = 0;
+ goto out;
+ }
+
+ error = EINVAL;
+ }
+ lldp_unref(ofport->lldp);
+ ofport->lldp = NULL;
+out:
+ ofproto_dpif_monitor_port_update(ofport,
+ ofport->bfd,
+ ofport->cfm,
+ ofport->lldp,
+ ofport->up.pp.hw_addr);
+ return error;
+}
+
+static bool
+get_lldp_status(const struct ofport *ofport_,
+ struct lldp_status *status OVS_UNUSED)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+
+ return ofport->lldp ? true : false;
+}
+
+static int
+set_aa(struct ofproto *ofproto OVS_UNUSED,
+ const struct aa_settings *s)
+{
+ return aa_configure(s);
+}
+
+static int
+aa_mapping_set(struct ofproto *ofproto_ OVS_UNUSED, void *aux,
+ const struct aa_mapping_settings *s)
+{
+ return aa_mapping_register(aux, s);
+}
+
+static int
+aa_mapping_unset(struct ofproto *ofproto OVS_UNUSED, void *aux)
+{
+ return aa_mapping_unregister(aux);
+}
+
+static int
+aa_vlan_get_queued(struct ofproto *ofproto OVS_UNUSED, struct ovs_list *list)
+{
+ return aa_get_vlan_queued(list);
+}
+
+static unsigned int
+aa_vlan_get_queue_size(struct ofproto *ofproto OVS_UNUSED)
+{
+ return aa_get_vlan_queue_size();
+}
+
/* Spanning Tree. */
@@ -5602,6 +5683,13 @@ const struct ofproto_class ofproto_dpif_class = {
set_cfm,
cfm_status_changed,
get_cfm_status,
+ set_lldp,
+ get_lldp_status,
+ set_aa,
+ aa_mapping_set,
+ aa_mapping_unset,
+ aa_vlan_get_queued,
+ aa_vlan_get_queue_size,
set_bfd,
bfd_status_changed,
get_bfd_status,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index d114390..2300537 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -1034,16 +1034,17 @@ struct ofproto_class {
* problem), or -1 if LACP is not enabled on 'port'.
*
* This function may be a null pointer if the ofproto implementation does
- * not support LACP. */
+ * not support LACP.
+ */
int (*port_is_lacp_current)(const struct ofport *port);
/* Get LACP port stats. Returns -1 if LACP is not enabled on 'port'.
*
* This function may be a null pointer if the ofproto implementation does
- * not support LACP. */
+ * not support LACP.
+ */
int (*port_get_lacp_stats)(const struct ofport *port,
- struct lacp_slave_stats *stats);
-
+ struct lacp_slave_stats *stats);
/* ## ----------------------- ## */
/* ## OpenFlow Rule Functions ## */
@@ -1359,6 +1360,77 @@ struct ofproto_class {
int (*get_cfm_status)(const struct ofport *ofport,
struct cfm_status *status);
+ /* Configures LLDP on 'ofport'.
+ *
+ * EOPNOTSUPP as a return value indicates that this ofproto_class does not
+ * support LLDP, as does a null pointer. */
+ int (*set_lldp)(struct ofport *ofport, const struct smap *cfg);
+
+ /* Checks the status of LLDP configured on 'ofport'. Returns true if the
+ * port's LLDP status was successfully stored into '*status'. Returns
+ * false if the port did not have LLDP configured, in which case '*status'
+ * is indeterminate.
+ *
+ * The caller must provide and own '*status'. '*status' is indeterminate
+ * if the return value is non-zero. */
+ bool (*get_lldp_status)(const struct ofport *ofport,
+ struct lldp_status *status);
+
+ /* Configures Auto Attach.
+ *
+ * If 's' is nonnull, configures Auto Attach according to its members.
+ *
+ * If 's' is null, removes any Auto Attach configuration.
+ */
+ int (*set_aa)(struct ofproto *ofproto,
+ const struct aa_settings *s);
+
+ /* If 's' is nonnull, this function registers a mapping associated with
+ * client data pointer 'aux' in 'ofproto'. If 'aux' is already registered
+ * then this function updates its configuration to 's'. Otherwise, this
+ * function registers a new mapping.
+ *
+ * An implementation that does not support mapping at all may set
+ * it to NULL or return EOPNOTSUPP. An implementation that supports
+ * only a subset of the functionality should implement what it can
+ * and return 0.
+ */
+ int (*aa_mapping_set)(struct ofproto *ofproto, void *aux,
+ const struct aa_mapping_settings *s);
+
+ /* If 's' is nonnull, this function unregisters a mapping associated with
+ * client data pointer 'aux' in 'ofproto'. If 'aux' is already registered
+ * then this function updates its configuration to 's'. Otherwise, this
+ * function unregisters a new mapping.
+ *
+ * An implementation that does not support mapping at all may set
+ * it to NULL or return EOPNOTSUPP. An implementation that supports
+ * only a subset of the functionality should implement what it can
+ * and return 0.
+ */
+ int (*aa_mapping_unset)(struct ofproto *ofproto, void *aux);
+
+ /*
+ * Returns the a list of AutoAttach VLAN operations. When Auto Attach is
+ * enabled, the VLAN associated with an I-SID/VLAN mapping is first
+ * negotiated with an Auto Attach Server. Once an I-SID VLAN mapping
+ * becomes active, the corresponding VLAN needs to be communicated to the
+ * bridge in order to add the VLAN to the trunk port linking the Auto
+ * Attach Client (in this case openvswitch) and the Auto Attach Server.
+ *
+ * The list entries are of type "struct bridge_aa_vlan". Each entry
+ * specifies the operation (add or remove), the interface on which to
+ * execute the operation and the VLAN.
+ */
+ int (*aa_vlan_get_queued)(struct ofproto *ofproto, struct ovs_list *list);
+
+ /*
+ * Returns the current number of entries in the list of VLAN operations
+ * in the Auto Attach Client (see previous function description
+ * aa_vlan_get_queued). Returns 0 if Auto Attach is disabled.
+ */
+ unsigned int (*aa_vlan_get_queue_size)(struct ofproto *ofproto);
+
/* Configures BFD on 'ofport'.
*
* If 'cfg' is NULL, or 'cfg' does not contain the key value pair
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index ba4263e..860d495 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1037,6 +1037,83 @@ ofproto_port_set_queues(struct ofproto *ofproto,
ofp_port_t ofp_port,
: EOPNOTSUPP);
}
+/* LLDP configuration. */
+void
+ofproto_port_set_lldp(struct ofproto *ofproto,
+ ofp_port_t ofp_port,
+ const struct smap *cfg)
+{
+ struct ofport *ofport;
+ int error;
+
+ ofport = ofproto_get_port(ofproto, ofp_port);
+ if (!ofport) {
+ VLOG_WARN("%s: cannot configure LLDP on nonexistent port %"PRIu16,
+ ofproto->name, ofp_port);
+ return;
+ }
+ error = (ofproto->ofproto_class->set_lldp
+ ? ofproto->ofproto_class->set_lldp(ofport, cfg)
+ : EOPNOTSUPP);
+ if (error) {
+ VLOG_WARN("%s: lldp configuration on port %"PRIu16" (%s) failed (%s)",
+ ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
+ ovs_strerror(error));
+ }
+}
+
+int
+ofproto_set_aa(struct ofproto *ofproto, void *aux OVS_UNUSED,
+ const struct aa_settings *s)
+{
+ if (!ofproto->ofproto_class->set_aa) {
+ return EOPNOTSUPP;
+ }
+ ofproto->ofproto_class->set_aa(ofproto, s);
+ return 0;
+}
+
+int
+ofproto_aa_mapping_register(struct ofproto *ofproto, void *aux,
+ const struct aa_mapping_settings *s)
+{
+ if (!ofproto->ofproto_class->aa_mapping_set) {
+ return EOPNOTSUPP;
+ }
+ ofproto->ofproto_class->aa_mapping_set(ofproto, aux, s);
+ return 0;
+}
+
+int
+ofproto_aa_mapping_unregister(struct ofproto *ofproto, void *aux)
+{
+ if (!ofproto->ofproto_class->aa_mapping_unset) {
+ return EOPNOTSUPP;
+ }
+ ofproto->ofproto_class->aa_mapping_unset(ofproto, aux);
+ return 0;
+}
+
+int
+ofproto_aa_vlan_get_queued(struct ofproto *ofproto,
+ struct ovs_list *list)
+{
+ if (!ofproto->ofproto_class->aa_vlan_get_queued) {
+ return EOPNOTSUPP;
+ }
+ ofproto->ofproto_class->aa_vlan_get_queued(ofproto, list);
+ return 0;
+}
+
+unsigned int
+ofproto_aa_vlan_get_queue_size(struct ofproto *ofproto)
+{
+ if (!ofproto->ofproto_class->aa_vlan_get_queue_size) {
+ return EOPNOTSUPP;
+ }
+ return ofproto->ofproto_class->aa_vlan_get_queue_size(ofproto);
+}
+
/* Connectivity Fault Management configuration. */
/* Clears the CFM configuration from 'ofp_port' on 'ofproto'. */
@@ -1217,7 +1294,8 @@ ofproto_mirror_unregister(struct ofproto *ofproto, void
*aux)
/* Retrieves statistics from mirror associated with client data pointer
* 'aux' in 'ofproto'. Stores packet and byte counts in 'packets' and
* 'bytes', respectively. If a particular counters is not supported,
- * the appropriate argument is set to UINT64_MAX. */
+ * the appropriate argument is set to UINT64_MAX.
+ */
int
ofproto_mirror_get_stats(struct ofproto *ofproto, void *aux,
uint64_t *packets, uint64_t *bytes)
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 261bc3b..5f331c7 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -46,6 +46,12 @@ struct ofport;
struct ofproto;
struct shash;
struct simap;
+struct smap;
+struct netdev_stats;
+struct ovs_list;
+struct lldp_status;
+struct aa_settings;
+struct aa_mapping_settings;
/* Needed for the lock annotations. */
extern struct ovs_mutex ofproto_mutex;
@@ -430,6 +436,16 @@ int ofproto_mirror_unregister(struct ofproto *, void *aux);
int ofproto_mirror_get_stats(struct ofproto *, void *aux,
uint64_t *packets, uint64_t *bytes);
+void ofproto_port_set_lldp(struct ofproto *ofproto, ofp_port_t ofp_port,
+ const struct smap *cfg);
+int ofproto_set_aa(struct ofproto *ofproto, void *aux,
+ const struct aa_settings *s);
+int ofproto_aa_mapping_register(struct ofproto *ofproto, void *aux,
+ const struct aa_mapping_settings *s);
+int ofproto_aa_mapping_unregister(struct ofproto *ofproto, void *aux);
+int ofproto_aa_vlan_get_queued(struct ofproto *ofproto, struct ovs_list *list);
+unsigned int ofproto_aa_vlan_get_queue_size(struct ofproto *ofproto);
+
int ofproto_set_flood_vlans(struct ofproto *, unsigned long *flood_vlans);
bool ofproto_is_mirror_output_bundle(const struct ofproto *, void *aux);
--
1.8.3.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev