Notifying Events on a Chain
Notifications are generated with notifier_call_chain. This function simply invokes, in order of priority, all the callback routines registered against the chain. Note that callback routines are executed in the context of the process that calls notifier_call_chain. A callback routine could, however, be implemented so that it queues the notification somewhere and wakes up a process that will look at it.
NOTE: Similar to register and unregister functions we don't directly call notifier_call_chain function as we have wrapper functions for respective chains.
<kernel/notifier.c> 58 static int __kprobes notifier_call_chain(struct notifier_block **nl, 59 unsigned long val, void *v, 60 int nr_to_call, int *nr_calls) 61 { 62 int ret = NOTIFY_DONE; 63 struct notifier_block *nb, *next_nb; 64 65 nb = rcu_dereference(*nl); 66 67 while (nb && nr_to_call) { 68 next_nb = rcu_dereference(nb->next); 69 ret = nb->notifier_call(nb, val, v); . 76 nb = next_nb; 77 nr_to_call--; 78 } 79 return ret; 80 }
- nl
Notification chain. - val
Event type. The chain itself identifies a class of events; val unequivocally identifies an event type (i.e., NETDEV_REGISTER). - v
Input parameter that can be used by the handlers registered by the various clients. This can be used in different ways under different circumstances. For instance, when a new network device is registered with the kernel, the associated notification uses v to identify the net_device data structure. - nr_to_call
Number of notifier functions to be called. Don't care value of this parameter is -1. - nr_calls
Records the number of notifications sent. Don't care value of this field is NULL.
Example of notifier chains in Network Subsystem
Let us see an example of using the notifier chains in bridge subsystem.
<net/bridge/br_notify.c> 24 struct notifier_block br_device_notifier = { 25 .notifier_call = br_device_event 26 }; <net/bridge/br.c> 30 static int __init br_init(void) 31 { . 48 err = register_netdevice_notifier(&br_device_notifier); . 72 }Once we fill the br_device_notifier we are registering to netdevice chain by calling the function register_netdevice_notifier(). netdev_chain is the head of the netdevice chain.
<net/core/dev.c> 245 static RAW_NOTIFIER_HEAD(netdev_chain); . 1129 int register_netdevice_notifier(struct notifier_block *nb) 1130 { . 1136 rtnl_lock(); 1137 err = raw_notifier_chain_register(&netdev_chain, nb); 1138 if (err) 1139 goto unlock; . 1177 }When any events occur we invoke all the registered functions via notifier_call_chain function.
<net/core/dev.c> 1208 int call_netdevice_notifiers(unsigned long val, struct net_device *dev) 1209 { 1210 return raw_notifier_call_chain(&netdev_chain, val, dev); 1211 }Below is the list of event types supported by netdevice:
<include/linux/notifier.h> 181 /* netdevice notifier chain */ 182 #define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */ 183 #define NETDEV_DOWN 0x0002 184 #define NETDEV_REBOOT 0x0003 . 188 #define NETDEV_CHANGE 0x0004 /* Notify device state change */ 189 #define NETDEV_REGISTER 0x0005 190 #define NETDEV_UNREGISTER 0x0006 191 #define NETDEV_CHANGEMTU 0x0007 192 #define NETDEV_CHANGEADDR 0x0008 193 #define NETDEV_GOING_DOWN 0x0009 194 #define NETDEV_CHANGENAME 0x000A 195 #define NETDEV_FEAT_CHANGE 0x000BNow it is upto to the notified to write a switch case to invoke the appropriate internal function in their subsystem for processing the respective event.
<net/bridge/br_notify.c> 34 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 35 { . 43 /* not a port of a bridge */ 44 if (p == NULL) 45 return NOTIFY_DONE; . 49 switch (event) { 50 case NETDEV_CHANGEMTU: 51 dev_set_mtu(br->dev, br_min_mtu(br)); 52 break; 53 54 case NETDEV_CHANGEADDR: 55 spin_lock_bh(&br->lock); 56 br_fdb_changeaddr(p, dev->dev_addr); 57 br_stp_recalculate_bridge_id(br); 58 spin_unlock_bh(&br->lock); 59 break; 60 61 case NETDEV_CHANGE: 62 br_port_carrier_check(p); 63 break; . 72 case NETDEV_DOWN: 73 spin_lock_bh(&br->lock); 74 if (br->dev->flags & IFF_UP) 75 br_stp_disable_port(p); 76 spin_unlock_bh(&br->lock); 77 break; 78 79 case NETDEV_UP: 80 if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) { 81 spin_lock_bh(&br->lock); 82 br_stp_enable_port(p); 83 spin_unlock_bh(&br->lock); . 98 }We can say the whole notification mechanism is much more like call-back functions used to trigger appropriate functions when certain operation or an even happens.
No comments :
Post a Comment
Your comments are moderated