net: add change_carrier netdev op
authorJiri Pirko <jiri@resnulli.us>
Thu, 27 Dec 2012 23:49:37 +0000 (23:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 28 Dec 2012 23:24:18 +0000 (15:24 -0800)
This allows a driver to register change_carrier callback which will be
called whenever user will like to change carrier state. This is useful
for devices like dummy, gre, team and so on.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/core/dev.c

index c599e4782d454cc853a6a9c1491f38bd1c1509b4..0e1b92a0c1ec2e2e2e9adb38366600f06b5ab417 100644 (file)
@@ -891,6 +891,14 @@ struct netdev_fcoe_hbainfo {
  * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
  *                          struct net_device *dev)
+ *
+ * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier);
+ *     Called to change device carrier. Soft-devices (like dummy, team, etc)
+ *     which do not represent real hardware may define this to allow their
+ *     userspace components to manage their virtual carrier state. Devices
+ *     that determine carrier state from physical hardware properties (eg
+ *     network cables) or protocol-dependent mechanisms (eg
+ *     USB_CDC_NOTIFY_NETWORK_CONNECTION) should NOT implement this function.
  */
 struct net_device_ops {
        int                     (*ndo_init)(struct net_device *dev);
@@ -1008,6 +1016,8 @@ struct net_device_ops {
        int                     (*ndo_bridge_getlink)(struct sk_buff *skb,
                                                      u32 pid, u32 seq,
                                                      struct net_device *dev);
+       int                     (*ndo_change_carrier)(struct net_device *dev,
+                                                     bool new_carrier);
 };
 
 /*
@@ -2194,6 +2204,8 @@ extern int                dev_set_mtu(struct net_device *, int);
 extern void            dev_set_group(struct net_device *, int);
 extern int             dev_set_mac_address(struct net_device *,
                                            struct sockaddr *);
+extern int             dev_change_carrier(struct net_device *,
+                                          bool new_carrier);
 extern int             dev_hard_start_xmit(struct sk_buff *skb,
                                            struct net_device *dev,
                                            struct netdev_queue *txq);
index 515473ee52cbb6327a9310922d0fb1c3d763df2f..21c5b976dcf3b649f49c15298dc545cf3daa5004 100644 (file)
@@ -5027,6 +5027,25 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 }
 EXPORT_SYMBOL(dev_set_mac_address);
 
+/**
+ *     dev_change_carrier - Change device carrier
+ *     @dev: device
+ *     @new_carries: new value
+ *
+ *     Change device carrier
+ */
+int dev_change_carrier(struct net_device *dev, bool new_carrier)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       if (!ops->ndo_change_carrier)
+               return -EOPNOTSUPP;
+       if (!netif_device_present(dev))
+               return -ENODEV;
+       return ops->ndo_change_carrier(dev, new_carrier);
+}
+EXPORT_SYMBOL(dev_change_carrier);
+
 /*
  *     Perform the SIOCxIFxxx calls, inside rcu_read_lock()
  */