NULL, /* get_in6 */
NULL, /* add_router */
NULL, /* get_next_hop */
- NULL, /* get_tnl_iface */
+ NULL, /* get_status */
NULL, /* arp_lookup */
netdev_dummy_update_flags,
netdev_linux_get_in6, \
netdev_linux_add_router, \
netdev_linux_get_next_hop, \
- NULL, /* get_tnl_iface */ \
+ NULL, /* get_status */ \
netdev_linux_arp_lookup, \
\
netdev_linux_update_flags, \
int (*get_next_hop)(const struct in_addr *host, struct in_addr *next_hop,
char **netdev_name);
- /* Looks up the name of the interface out of which traffic will egress if
- * 'netdev' is a tunnel. If unsuccessful, or 'netdev' is not a tunnel,
- * will return null. This function does not necessarily return the
- * physical interface out which traffic will egress. Instead it returns
- * the interface which is assigned 'netdev's remote_ip. This may be an
- * internal interface such as a bridge port.
- *
- * This function may be set to null if 'netdev' is not a tunnel or it is
- * not supported. */
- const char *(*get_tnl_iface)(const struct netdev *netdev);
+ /* Retrieves the status of the device.
+ *
+ * Populates 'sh' with key-value pairs representing the status of the
+ * device. A device's status is a set of key-value string pairs
+ * representing netdev type specific information. For more information see
+ * ovs-vswitchd.conf.db(5).
+ *
+ * The data of 'sh' are heap allocated strings which the caller is
+ * responsible for deallocating.
+ *
+ * This function may be set to null if it would always return EOPNOTSUPP
+ * anyhow. */
+ int (*get_status)(const struct netdev *netdev, struct shash *sh);
/* Looks up the ARP table entry for 'ip' on 'netdev' and stores the
* corresponding MAC address in 'mac'. A return value of ENXIO, in
void *);
static void netdev_vport_link_change(const struct rtnetlink_link_change *,
void *);
+static const char *netdev_vport_get_tnl_iface(const struct netdev *netdev);
static bool
is_vport_class(const struct netdev_class *class)
return err;
}
+static int
+netdev_vport_get_status(const struct netdev *netdev, struct shash *sh)
+{
+ const char *iface = netdev_vport_get_tnl_iface(netdev);
+
+ if (iface) {
+ shash_add(sh, "tunnel_egress_iface", xstrdup(iface));
+ }
+
+ return 0;
+}
+
static int
netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED,
enum netdev_flags off, enum netdev_flags on OVS_UNUSED,
return 0;
}
\f
-#define VPORT_FUNCTIONS(TNL_IFACE) \
+#define VPORT_FUNCTIONS(GET_STATUS) \
netdev_vport_init, \
netdev_vport_run, \
netdev_vport_wait, \
NULL, /* get_in6 */ \
NULL, /* add_router */ \
NULL, /* get_next_hop */ \
- TNL_IFACE, \
+ GET_STATUS, \
NULL, /* arp_lookup */ \
\
netdev_vport_update_flags, \
netdev_vport_register(void)
{
static const struct vport_class vport_classes[] = {
- { { "gre", VPORT_FUNCTIONS(netdev_vport_get_tnl_iface) },
+ { { "gre", VPORT_FUNCTIONS(netdev_vport_get_status) },
parse_tunnel_config },
- { { "ipsec_gre", VPORT_FUNCTIONS(netdev_vport_get_tnl_iface) },
+ { { "ipsec_gre", VPORT_FUNCTIONS(netdev_vport_get_status) },
parse_tunnel_config },
- { { "capwap", VPORT_FUNCTIONS(netdev_vport_get_tnl_iface) },
+ { { "capwap", VPORT_FUNCTIONS(netdev_vport_get_status) },
parse_tunnel_config },
{ { "patch", VPORT_FUNCTIONS(NULL) }, parse_patch_config }
};
return error;
}
-const char *
-netdev_get_tnl_iface(const struct netdev *netdev)
+/* Populates 'sh' with status information.
+ *
+ * Populates 'sh' with 'netdev' specific status information. This information
+ * may be used to populate the status column of the Interface table as defined
+ * in ovs-vswitchd.conf.db(5). */
+int
+netdev_get_status(const struct netdev *netdev, struct shash *sh)
{
struct netdev_dev *dev = netdev_get_dev(netdev);
- return (dev->netdev_class->get_tnl_iface
- ? dev->netdev_class->get_tnl_iface(netdev)
- : NULL);
+ return (dev->netdev_class->get_status
+ ? dev->netdev_class->get_status(netdev, sh)
+ : EOPNOTSUPP);
}
/* If 'netdev' has an assigned IPv6 address, sets '*in6' to that address and
int netdev_add_router(struct netdev *, struct in_addr router);
int netdev_get_next_hop(const struct netdev *, const struct in_addr *host,
struct in_addr *next_hop, char **);
-const char *netdev_get_tnl_iface(const struct netdev *);
+int netdev_get_status(const struct netdev *, struct shash *sh);
int netdev_arp_lookup(const struct netdev *, uint32_t ip, uint8_t mac[6]);
int netdev_get_flags(const struct netdev *, enum netdev_flags *);
static void shash_from_ovs_idl_map(char **keys, char **values, size_t n,
struct shash *);
+static void shash_to_ovs_idl_map(struct shash *,
+ char ***keys, char ***values, size_t *n);
+
/* Hooks into ofproto processing. */
static struct ofhooks bridge_ofhooks;
}
static void
-iface_refresh_tunnel_egress(struct iface *iface)
+iface_refresh_status(struct iface *iface)
{
- const char *name = netdev_get_tnl_iface(iface->netdev);
+ struct shash sh;
+
+ shash_init(&sh);
+
+ if (!netdev_get_status(iface->netdev, &sh)) {
+ size_t n;
+ char **keys, **values;
- ovsrec_interface_set_tunnel_egress_iface(iface->cfg, name);
+ shash_to_ovs_idl_map(&sh, &keys, &values, &n);
+ ovsrec_interface_set_status(iface->cfg, keys, values, n);
+
+ free(keys);
+ free(values);
+ } else {
+ ovsrec_interface_set_status(iface->cfg, NULL, NULL, 0);
+ }
+
+ shash_destroy_free_data(&sh);
}
static void
struct iface *iface = port->ifaces[j];
iface_refresh_stats(iface);
iface_refresh_cfm_stats(iface);
- iface_refresh_tunnel_egress(iface);
+ iface_refresh_status(iface);
}
}
}
}
}
+/* Creates 'keys' and 'values' arrays from 'shash'.
+ *
+ * Sets 'keys' and 'values' to heap allocated arrays representing the key-value
+ * pairs in 'shash'. The caller takes ownership of 'keys' and 'values'. They
+ * are populated with with strings taken directly from 'shash' and thus have
+ * the same ownership of the key-value pairs in shash.
+ */
+static void
+shash_to_ovs_idl_map(struct shash *shash,
+ char ***keys, char ***values, size_t *n)
+{
+ size_t i, count;
+ char **k, **v;
+ struct shash_node *sn;
+
+ count = shash_count(shash);
+
+ k = xmalloc(count * sizeof *k);
+ v = xmalloc(count * sizeof *v);
+
+ i = 0;
+ SHASH_FOR_EACH(sn, shash) {
+ k[i] = sn->name;
+ v[i] = sn->data;
+ i++;
+ }
+
+ *n = count;
+ *keys = k;
+ *values = v;
+}
+
struct iface_delete_queues_cbdata {
struct netdev *netdev;
const struct ovsdb_datum *queues;
{"name": "Open_vSwitch",
- "version": "1.0.2",
- "cksum": "3196651018 14282",
+ "version": "1.0.3",
+ "cksum": "2654345387 14137",
"tables": {
"Open_vSwitch": {
"columns": {
"ingress_policing_burst": {
"type": {"key": {"type": "integer",
"minInteger": 0}}},
- "tunnel_egress_iface": {
- "type": {"key": {"type": "string"},
- "min": 0, "max": 1},
- "ephemeral": true},
"mac": {
"type": {"key": {"type": "string"},
"min": 0, "max": 1}},
Key-value pairs that report port status. Supported status
values are <code>type</code>-dependent.
</p>
- <p>The only currently defined key-value pair is:</p>
+ <p>The currently defined key-value pairs are:</p>
<dl>
<dt><code>source_ip</code></dt>
<dd>The source IP address used for an IPv4 tunnel end-point,
such as <code>gre</code> or <code>capwap</code>. Not
supported by all implementations.</dd>
</dl>
+ <dl>
+ <dt><code>tunnel_egress_iface</code></dt>
+ <dd>Egress interface for tunnels. Currently only relevant for GRE
+ and CAPWAP tunnels. On Linux systems, this column will show
+ the name of the interface which is responsible for routing
+ traffic destined for the configured <code>remote_ip</code>.
+ This could be an internal interface such as a bridge port.</dd>
+ </dl>
</column>
</group>
</dl>
</column>
- <column name="tunnel_egress_iface">
- Egress interface for tunnels. Currently only relevant for GRE and
- CAPWAP tunnels. On Linux systems, this column will show the name of
- the interface which is responsible for routing traffic destined for the
- configured <code>remote_ip</code>. This could be an internal interface
- such as a bridge port.
- </column>
-
<column name="other_config">
Key-value pairs for rarely used interface features. Currently,
there are none defined.