* If the 'may_open' flag is set then the call will succeed even if another
* caller has already opened it. It may be to false if the device should not
* currently be open. */
-
int
netdev_open(struct netdev_options *options, struct netdev **netdevp)
{
return netdev_open(&options, netdevp);
}
+/* Increments the reference count on 'netdev'. Returns 'netdev'. */
+struct netdev *
+netdev_reopen(struct netdev *netdev)
+{
+ netdev->ref_cnt++;
+ return netdev;
+}
+
/* Reconfigures the device 'netdev' with 'args'. 'args' may be empty
* or NULL if none are needed. */
int
return 0;
}
-/* Closes and destroys 'netdev'. */
+/* Decrements the reference count on 'netdev'. If the reference count reaches
+ * zero, closes and destroys 'netdev'. */
void
netdev_close(struct netdev *netdev)
{
- if (netdev) {
+ assert(!netdev || netdev->ref_cnt > 0);
+ if (netdev && !--netdev->ref_cnt) {
struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
assert(netdev_dev->ref_cnt);
* value should be unique within a host and remain stable at least until
* reboot. SNMP says an ifindex "ranges between 1 and the value of ifNumber"
* but many systems do not follow this rule anyhow.
+ *
+ * Some network devices may not implement support for this function. In such
+ * cases this function will always return -EOPNOTSUPP.
*/
int
netdev_get_ifindex(const struct netdev *netdev)
{
- return netdev_get_dev(netdev)->netdev_class->get_ifindex(netdev);
+ int (*get_ifindex)(const struct netdev *);
+
+ get_ifindex = netdev_get_dev(netdev)->netdev_class->get_ifindex;
+
+ return get_ifindex ? get_ifindex(netdev) : -EOPNOTSUPP;
}
/* Stores the features supported by 'netdev' into each of '*current',
* '*advertised', '*supported', and '*peer' that are non-null. Each value is a
* bitmap of "enum ofp_port_features" bits, in host byte order. Returns 0 if
* successful, otherwise a positive errno value. On failure, all of the
- * passed-in values are set to 0. */
+ * passed-in values are set to 0.
+ *
+ * Some network devices may not implement support for this function. In such
+ * cases this function will always return EOPNOTSUPP.
+ */
int
netdev_get_features(struct netdev *netdev,
uint32_t *current, uint32_t *advertised,
uint32_t *supported, uint32_t *peer)
{
+ int (*get_features)(struct netdev *netdev,
+ uint32_t *current, uint32_t *advertised,
+ uint32_t *supported, uint32_t *peer);
uint32_t dummy[4];
int error;
peer = &dummy[3];
}
- error = netdev_get_dev(netdev)->netdev_class->get_features(netdev, current,
- advertised, supported, peer);
+ get_features = netdev_get_dev(netdev)->netdev_class->get_features;
+ error = get_features
+ ? get_features(netdev, current, advertised, supported, peer)
+ : EOPNOTSUPP;
if (error) {
*current = *advertised = *supported = *peer = 0;
}
return error;
}
+/* Attempts to change the stats for 'netdev' to those provided in 'stats'.
+ * Returns 0 if successful, otherwise a positive errno value.
+ *
+ * This will probably fail for most network devices. Some devices might only
+ * allow setting their stats to 0. */
+int
+netdev_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
+{
+ return (netdev_get_dev(netdev)->netdev_class->set_stats
+ ? netdev_get_dev(netdev)->netdev_class->set_stats(netdev, stats)
+ : EOPNOTSUPP);
+}
+
/* Attempts to set input rate limiting (policing) policy, such that up to
* 'kbits_rate' kbps of traffic is accepted, with a maximum accumulative burst
* size of 'kbits' kb. */
{
memset(netdev, 0, sizeof *netdev);
netdev->netdev_dev = netdev_dev;
+ netdev->ref_cnt = 1;
list_push_back(&netdev_list, &netdev->node);
}
*
* Normally this function only needs to be called from netdev_close().
* However, it may be called by providers due to an error on opening
- * that occurs after initialization. It this case netdev_close() would
+ * that occurs after initialization. In this case netdev_close() would
* never be called. */
void
netdev_uninit(struct netdev *netdev, bool close)