From: Dennis Flynn <drfl...@avaya.com> Signed-off-by: Ludovic Beliveau <ludovic.beliv...@windriver.com> Signed-off-by: Dennis Flynn <drfl...@avaya.com>
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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev