- if (current == iface)
- last_ev = current_ev;
- else
- last_ev = iface->hotplug_ev;
-
- iface->hotplug_ev = ev;
- if ((last_ev == ev && ev != IFEV_UPDATE) && !list_empty(&iface->hotplug_list))
- list_del_init(&iface->hotplug_list);
- else if ((last_ev != ev || ev == IFEV_UPDATE) && list_empty(&iface->hotplug_list))
- list_add(&iface->hotplug_list, &pending);
+ if (current == iface) {
+ /* an event for iface is being processed */
+ if (!list_empty(&iface->hotplug_list)) {
+ /* an additional event for iface is pending */
+ if ((ev != current_ev || ev == IFEV_UPDATE) &&
+ !(iface->hotplug_ev == IFEV_UP && ev == IFEV_UPDATE)) {
+ /* if incoming event is different from the one
+ * being handled or if it is an update,
+ * overwrite pending event, but never
+ * overwrite an ifup with an ifupdate */
+ iface->hotplug_ev = ev;
+ }
+ else if (ev == current_ev && ev != IFEV_UPDATE) {
+ /* if incoming event is not an ifupdate
+ * and is the same as the one that is
+ * being handled, remove it from the
+ * pending list */
+ list_del_init(&iface->hotplug_list);
+ }
+ }
+ else {
+ /* no additional event for iface is pending */
+ if (ev != current_ev || ev == IFEV_UPDATE) {
+ /* only add the interface to the pending list if
+ * the event is different from the one being
+ * handled or if it is an update */
+ iface->hotplug_ev = ev;
+ /* Handle hotplug calls FIFO */
+ list_add_tail(&iface->hotplug_list, &pending);
+ }
+ }
+ }
+ else {
+ /* currently not handling an event or handling an event
+ * for another interface */
+ if (!list_empty(&iface->hotplug_list)) {
+ /* an event for iface is pending */
+ if (!(iface->hotplug_ev == IFEV_UP &&
+ ev == IFEV_UPDATE)) {
+ /* overwrite pending event, unless the incoming
+ * event is an ifupdate while the pending one
+ * is an ifup */
+ iface->hotplug_ev = ev;
+ }
+ }
+ else {
+ /* an event for the interface is not yet pending,
+ * queue it */
+ iface->hotplug_ev = ev;
+ /* Handle hotplug calls FIFO */
+ list_add_tail(&iface->hotplug_list, &pending);
+ }
+ }