auto-attach: Add auto-attach support to ofproto layer
authorDennis Flynn <drflynn@avaya.com>
Fri, 20 Feb 2015 19:17:10 +0000 (14:17 -0500)
committerBen Pfaff <blp@nicira.com>
Wed, 4 Mar 2015 00:19:26 +0000 (16:19 -0800)
Signed-off-by: Ludovic Beliveau <ludovic.beliveau@windriver.com>
Signed-off-by: Dennis Flynn <drflynn@avaya.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
18 files changed:
lib/bfd.c
lib/bfd.h
lib/cfm.c
lib/cfm.h
lib/lldp/lldp.c
lib/lldp/lldpd.c
lib/lldp/lldpd.h
lib/odp-util.h
lib/ovs-lldp.c
lib/ovs-lldp.h
ofproto/ofproto-dpif-monitor.c
ofproto/ofproto-dpif-monitor.h
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif-xlate.h
ofproto/ofproto-dpif.c
ofproto/ofproto-provider.h
ofproto/ofproto.c
ofproto/ofproto.h

index c463b66..92fdbd8 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -516,10 +516,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. */
index 2f1924c..19d294f 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -31,7 +31,7 @@ struct netdev;
 struct dp_packet;
 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 *);
index 3e7cfe6..380c5b0 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -564,7 +564,7 @@ cfm_should_send_ccm(struct cfm *cfm) OVS_EXCLUDED(mutex)
  * should be sent whenever cfm_should_send_ccm() indicates. */
 void
 cfm_compose_ccm(struct cfm *cfm, struct dp_packet *packet,
-                uint8_t eth_src[ETH_ADDR_LEN]) OVS_EXCLUDED(mutex)
+                const uint8_t eth_src[ETH_ADDR_LEN]) OVS_EXCLUDED(mutex)
 {
     uint16_t ccm_vlan;
     struct ccm *ccm;
@@ -629,10 +629,12 @@ cfm_compose_ccm(struct cfm *cfm, struct dp_packet *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;
 }
 
 
index a871ba8..5ef8639 100644 (file)
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2010, 2011, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -93,8 +93,9 @@ struct cfm *cfm_ref(const struct cfm *);
 void cfm_unref(struct cfm *);
 void cfm_run(struct cfm *);
 bool cfm_should_send_ccm(struct cfm *);
-void cfm_compose_ccm(struct cfm *, struct dp_packet *packet, uint8_t eth_src[ETH_ADDR_LEN]);
-void cfm_wait(struct cfm *);
+void cfm_compose_ccm(struct cfm *, struct dp_packet *,
+                     const uint8_t eth_src[ETH_ADDR_LEN]);
+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 *,
index 5838a07..2a581ac 100644 (file)
@@ -25,8 +25,8 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include "compiler.h"
+#include "dp-packet.h"
 #include "packets.h"
-#include "ofpbuf.h"
 
 VLOG_DEFINE_THIS_MODULE(lldp);
 
@@ -164,7 +164,7 @@ lldpd_af_from_lldp_proto(int proto)
 int
 lldp_send(struct lldpd *global OVS_UNUSED,
           struct lldpd_hardware *hardware,
-          struct ofpbuf *p)
+          struct dp_packet *p)
 {
     struct lldpd_port *port;
     struct lldpd_chassis *chassis;
@@ -181,16 +181,16 @@ lldp_send(struct lldpd *global OVS_UNUSED,
 
     /* The ethernet header is filled in elsewhere, we must save room for it. */
     length = hardware->h_mtu - sizeof(struct eth_header);
-    packet = ofpbuf_l3(p);
+    packet = dp_packet_l3(p);
     VLOG_DBG("LLDP PDU send to %s mtu %d incoming with ptr=%p",
               hardware->h_ifname, hardware->h_mtu, packet);
     pos = packet;
 
     /*
-     * Make room in ofpbuf for chassis ID, Port ID, System Name, System Descr,
-     * System Cap
+     * Make room in dp_packet for chassis ID, Port ID, System Name, System
+     * Descr, System Cap
      */
-    pos = ofpbuf_put_uninit(p, sizeof chassis->c_id_subtype +
+    pos = dp_packet_put_uninit(p, sizeof chassis->c_id_subtype +
                                chassis->c_id_len +
                                sizeof port->p_id_subtype +
                                port->p_id_len +
@@ -253,7 +253,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
        /*
         * Make room for 1 mgmt interface
         */
-        ofpbuf_put_uninit(p, 2 + sizeof(uint8_t) +
+        dp_packet_put_uninit(p, 2 + sizeof(uint8_t) +
                              sizeof(uint8_t) +
                              mgmt->m_addrsize +
                              sizeof(uint8_t) +
@@ -293,7 +293,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
     /* Port description */
     if (port->p_descr && *port->p_descr != '\0') {
         /* make room for port descr */
-        ofpbuf_put_uninit(p, 2 + strlen(port->p_descr));
+        dp_packet_put_uninit(p, 2 + strlen(port->p_descr));
 
         if (!(POKE_START_LLDP_TLV(LLDP_TLV_PORT_DESCR) &&
               POKE_BYTES(port->p_descr, strlen(port->p_descr)) &&
@@ -330,7 +330,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
         aa_elem_sys_id_second_byte = port->p_element.system_id.smlt_id & 0x0FF;
 
         /* make room for element type tlv */
-        ofpbuf_put_uninit(p, 2 + sizeof avaya +
+        dp_packet_put_uninit(p, 2 + sizeof avaya +
                              sizeof(uint8_t) +
                              sizeof aa_element_first_byte +
                              sizeof aa_element_second_byte +
@@ -361,7 +361,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
        /*
         * make room for aa_isid_digest
         */
-        ofpbuf_put_uninit(p, 2 + sizeof avaya +
+        dp_packet_put_uninit(p, 2 + sizeof avaya +
                              sizeof(uint8_t) +
                              sizeof msg_auth_digest);
 
@@ -387,7 +387,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
             /*
              * Make room for one isid-vlan mapping
              */
-            ofpbuf_put_uninit(p, sizeof status_vlan_word +
+            dp_packet_put_uninit(p, sizeof status_vlan_word +
                                  sizeof vlan_isid_map->isid_vlan_data.isid);
 
             if (!(POKE_UINT16(status_vlan_word) &&
@@ -403,7 +403,7 @@ lldp_send(struct lldpd *global OVS_UNUSED,
     }
 
     /* Make room for the End TLV 0x0000 */
-    ofpbuf_put_uninit(p, sizeof(uint16_t));
+    dp_packet_put_uninit(p, sizeof(uint16_t));
 
     /* END */
     if (!(POKE_START_LLDP_TLV(LLDP_TLV_END) &&
index 9c8173e..6b735e8 100644 (file)
@@ -585,7 +585,7 @@ lldpd_recv(struct lldpd *cfg,
 }
 
 uint32_t
-lldpd_send(struct lldpd_hardware *hw, struct ofpbuf *p)
+lldpd_send(struct lldpd_hardware *hw, struct dp_packet *p)
 {
     struct lldpd *cfg = hw->h_cfg;
     struct lldpd_port *port;
index f142180..f1eb6e3 100644 (file)
 #include <string.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include "dp-packet.h"
 #include "list.h"
 #include "lldpd-structs.h"
 #include "lldp-tlv.h"
 #include "packets.h"
 #include "openvswitch/vlog.h"
-#include "ofpbuf.h"
 
 #define SYSCONFDIR       ""
 #define LLDPD_CTL_SOCKET ""
@@ -56,7 +56,7 @@ struct event_base;
 
 #define USING_AGENTX_SUBAGENT_MODULE 1
 
-#define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *,struct ofpbuf *
+#define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *,struct dp_packet *
 #define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *,\
     struct lldpd_chassis **, struct lldpd_port **
 #define PROTO_GUESS_SIG char *, int
@@ -104,7 +104,7 @@ void lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
 struct lldpd_mgmt *lldpd_alloc_mgmt(int family, void *addr, size_t addrsize,
     u_int32_t iface);
 void lldpd_recv(struct lldpd *, struct lldpd_hardware *, char *, size_t);
-uint32_t lldpd_send(struct lldpd_hardware *, struct ofpbuf *);
+uint32_t lldpd_send(struct lldpd_hardware *, struct dp_packet *);
 void lldpd_loop(struct lldpd *);
 
 int lldpd_main(int, char **);
index 5765e25..4f0e794 100644 (file)
@@ -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",                                      \
index 5fbde7e..42ea49a 100644 (file)
@@ -39,7 +39,6 @@
 #include "lldp/lldpd.h"
 #include "lldp/lldpd-structs.h"
 #include "netdev.h"
-#include "ofpbuf.h"
 #include "openvswitch/types.h"
 #include "packets.h"
 #include "poll-loop.h"
@@ -736,7 +735,7 @@ lldp_should_process_flow(const struct flow *flow)
 /* Process an LLDP packet that was received on a bridge port.
  */
 void
-lldp_process_packet(struct lldp *lldp, const struct ofpbuf *p)
+lldp_process_packet(struct lldp *lldp, const struct dp_packet *p)
 {
     if (lldp) {
         lldpd_recv(lldp->lldpd,
@@ -793,7 +792,7 @@ lldp_wait(struct lldp *lldp) OVS_EXCLUDED(mutex)
 /* Prepare the LLDP packet to be sent on a bridge port.
  */
 void
-lldp_put_packet(struct lldp *lldp, struct ofpbuf *packet,
+lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
                 uint8_t eth_src[ETH_ADDR_LEN]) OVS_EXCLUDED(mutex)
 {
     struct lldpd *mylldpd = lldp->lldpd;
index e8167c7..c629aa0 100644 (file)
 #define OVS_LLDP_H
 
 #include <stdint.h>
+#include "dp-packet.h"
 #include "hmap.h"
 #include "list.h"
 #include "lldp/lldpd.h"
-#include "ofpbuf.h"
 #include "ovsdb-data.h"
 #include "ovs-thread.h"
 #include "packets.h"
@@ -91,8 +91,8 @@ void lldp_run(struct lldpd *cfg);
 bool lldp_should_send_packet(struct lldp *cfg);
 bool lldp_should_process_flow(const struct flow *flow);
 bool lldp_configure(struct lldp *lldp);
-void lldp_process_packet(struct lldp *cfg, const struct ofpbuf *p);
-void lldp_put_packet(struct lldp *lldp, struct ofpbuf *packet,
+void lldp_process_packet(struct lldp *cfg, const struct dp_packet *);
+void lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
                      uint8_t eth_src[ETH_ADDR_LEN]);
 void lldpd_assign_cfg_to_protocols(struct lldpd *cfg);
 struct lldp * lldp_create(const struct netdev *netdev, const uint32_t mtu,
index ed59f9e..252a5d8 100644 (file)
@@ -29,6 +29,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"
@@ -43,7 +44,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. */
@@ -51,6 +52,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. */
 };
 
@@ -86,12 +88,13 @@ static void monitor_run(void);
 static void monitor_mport_run(struct mport *, struct dp_packet *);
 
 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);
 
@@ -115,7 +118,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);
@@ -126,7 +129,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. */
@@ -137,7 +140,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);
@@ -147,7 +150,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);
 
@@ -159,12 +163,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);
     }
 }
@@ -260,6 +268,9 @@ monitor_mport_run(struct mport *mport, struct dp_packet *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)) {
         dp_packet_clear(packet);
@@ -271,17 +282,27 @@ monitor_mport_run(struct mport *mport, struct dp_packet *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)) {
+        dp_packet_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));
 }
@@ -294,13 +315,14 @@ monitor_mport_run(struct mport *mport, struct dp_packet *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);
 
index 2c466c2..b65d70b 100644 (file)
 
 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 */
index 647fa11..45227a8 100644 (file)
@@ -38,6 +38,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 {
@@ -388,8 +390,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);
@@ -531,7 +533,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)
@@ -558,6 +560,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);
@@ -625,9 +632,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);
@@ -864,8 +871,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,
@@ -888,8 +895,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;
@@ -951,6 +959,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);
 }
 
@@ -2529,6 +2538,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;
     }
index 5f3ad81..a53fa8e 100644 (file)
@@ -24,6 +24,7 @@
 #include "ofproto-dpif.h"
 #include "ofproto.h"
 #include "stp.h"
+#include "ovs-lldp.h"
 
 struct bfd;
 struct bond;
@@ -165,10 +166,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,
index 57a6f3e..9b67518 100644 (file)
@@ -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;
@@ -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);
 
@@ -1986,7 +1991,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;
 }
 
@@ -2028,7 +2033,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;
 }
 
@@ -2054,6 +2059,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();
+}
+
 \f
 /* Spanning Tree. */
 
@@ -5604,6 +5685,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,
index 4e67a09..7208541 100644 (file)
@@ -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
index 61fccb4..07a1f5d 100644 (file)
@@ -1038,6 +1038,83 @@ ofproto_port_set_queues(struct ofproto *ofproto, ofp_port_t ofp_port,
             : EOPNOTSUPP);
 }
 \f
+/* 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'. */
@@ -1218,7 +1295,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)
index 2d6e257..7dc1874 100644 (file)
@@ -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;
@@ -435,6 +441,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);