netifd: Reload proto on topology change
authorHelmut Schaa <helmut.schaa@googlemail.com>
Thu, 20 Mar 2014 15:26:23 +0000 (16:26 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 21 Mar 2014 15:05:20 +0000 (16:05 +0100)
Introduce a new device event "topology change" that gets signaled
by bridges on adding/removing members.

On "topology changes" the proto handlers are requested to "renew"
which is most useful for DHCP.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
bridge.c
device.h
interface.c
proto-shell.c
proto-static.c
proto.c
proto.h
scripts/netifd-proto.sh
vlan.c

index 147fe0a0c6d0d01f5ce85ed7a1384ec00b763ae2..6baef293dfcfc3692547d467ca213dc2b0923e22 100644 (file)
--- a/bridge.c
+++ b/bridge.c
@@ -140,6 +140,8 @@ bridge_disable_member(struct bridge_member *bm)
        system_bridge_delif(&bst->dev, bm->dev.dev);
        device_release(&bm->dev);
 
+       device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE);
+
        return 0;
 }
 
@@ -162,6 +164,8 @@ bridge_enable_member(struct bridge_member *bm)
                goto error;
        }
 
+       device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE);
+
        return 0;
 
 error:
index dd57927620ffb08bdfb0b953e0966d562fc257b0..e71027ee28888420dfd1d73c5cab0432248928e5 100644 (file)
--- a/device.h
+++ b/device.h
@@ -78,6 +78,9 @@ enum device_event {
        DEV_EVENT_LINK_UP,
        DEV_EVENT_LINK_DOWN,
 
+       /* Topology changed (i.e. bridge member added) */
+       DEV_EVENT_TOPO_CHANGE,
+
        __DEV_EVENT_MAX
 };
 
index 4a3a725ce35aa9557ac75fee622a951af85e01ef..fa8e55e1060896758c7696a9325630f90e36a5d5 100644 (file)
@@ -328,6 +328,9 @@ interface_cb(struct device_user *dep, enum device_event ev)
         case DEV_EVENT_LINK_DOWN:
                interface_set_link_state(iface, new_state);
                break;
+       case DEV_EVENT_TOPO_CHANGE:
+               interface_proto_event(iface->proto, PROTO_CMD_RENEW, false);
+               return;
        default:
                break;
        }
@@ -599,6 +602,8 @@ interface_proto_cb(struct interface_proto_state *state, enum interface_proto_eve
                mark_interface_down(iface);
                iface->state = IFS_SETUP;
                break;
+       default:
+               return;
        }
 
        interface_write_resolv_conf();
index 904104551a1ce794eeecf5a036278cc98bfd6634..de1b084c5359da330e3a0304fb9c25a186eae6c2 100644 (file)
@@ -159,6 +159,10 @@ proto_shell_handler(struct interface_proto_state *proto,
                state->last_error = -1;
                proto_shell_clear_host_dep(state);
                state->sm = S_SETUP;
+       } else if (cmd == PROTO_CMD_RENEW) {
+               if (!(handler->proto.flags & PROTO_FLAG_RENEW_AVAILABLE))
+                       return 0;
+               action = "renew";
        } else {
                if (state->sm == S_TEARDOWN)
                        return 0;
@@ -761,6 +765,10 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj)
        if (tmp && json_object_get_boolean(tmp))
                handler->proto.flags |= PROTO_FLAG_INIT_AVAILABLE;
 
+       tmp = json_get_field(obj, "renew-handler", json_type_boolean);
+       if (tmp && json_object_get_boolean(tmp))
+               handler->proto.flags |= PROTO_FLAG_RENEW_AVAILABLE;
+
        config = json_get_field(obj, "config", json_type_array);
        if (config)
                handler->config_buf = netifd_handler_parse_config(&handler->config, config);
index 77a536a0cdce2375d8a08e8a4675bb44e0122481..b492d923985dd6ed0f3b6048b44faeca6c9ff30e 100644 (file)
@@ -52,6 +52,7 @@ static_handler(struct interface_proto_state *proto,
 
                break;
        case PROTO_CMD_TEARDOWN:
+       case PROTO_CMD_RENEW:
                break;
        }
 
diff --git a/proto.c b/proto.c
index 64be308c970a39e210401edf6d28eb66dc9d5d4e..3a7b2a832348b801998c11acb8327adaeed29fd3 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -615,6 +615,9 @@ interface_proto_event(struct interface_proto_state *proto,
        case PROTO_CMD_TEARDOWN:
                ev = IFPEV_DOWN;
                break;
+       case PROTO_CMD_RENEW:
+               ev = IFPEV_RENEW;
+               break;
        default:
                return -EINVAL;
        }
diff --git a/proto.h b/proto.h
index e402a91ed60d319128ccf698476699e61e709eb2..e7d84ac057e98832f142253045e8bc6ccab8bc2c 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -22,17 +22,20 @@ enum interface_proto_event {
        IFPEV_UP,
        IFPEV_DOWN,
        IFPEV_LINK_LOST,
+       IFPEV_RENEW,
 };
 
 enum interface_proto_cmd {
        PROTO_CMD_SETUP,
        PROTO_CMD_TEARDOWN,
+       PROTO_CMD_RENEW,
 };
 
 enum {
        PROTO_FLAG_IMMEDIATE = (1 << 0),
        PROTO_FLAG_NODEV = (1 << 1),
        PROTO_FLAG_INIT_AVAILABLE = (1 << 2),
+       PROTO_FLAG_RENEW_AVAILABLE = (1 << 3),
 };
 
 struct interface_proto_state {
index 7f08b1d15c725dd45b85b919712b6bb0d6026fa6..ce316c42386d0cfa29b2dab9debb54c1afb69c37 100644 (file)
@@ -20,6 +20,11 @@ _proto_do_teardown() {
        eval "proto_$1_teardown \"$interface\" \"$ifname\""
 }
 
+_proto_do_renew() {
+       json_load "$data"
+       eval "proto_$1_renew \"$interface\" \"$ifname\""
+}
+
 _proto_do_setup() {
        json_load "$data"
        _EXPORT_VAR=0
@@ -352,6 +357,7 @@ init_proto() {
                        add_protocol() {
                                no_device=0
                                available=0
+                               renew_handler=0
 
                                add_default_handler "proto_$1_init_config"
 
@@ -362,10 +368,11 @@ init_proto() {
                                json_close_array
                                json_add_boolean no-device "$no_device"
                                json_add_boolean available "$available"
+                               json_add_boolean renew-handler "$renew_handler"
                                json_dump
                        }
                ;;
-               setup|teardown)
+               setup|teardown|renew)
                        interface="$1"; shift
                        data="$1"; shift
                        ifname="$1"; shift
@@ -376,6 +383,7 @@ init_proto() {
                                case "$cmd" in
                                        setup) _proto_do_setup "$1";;
                                        teardown) _proto_do_teardown "$1" ;;
+                                       renew) _proto_do_renew "$1" ;;
                                        *) return 1 ;;
                                esac
                        }
diff --git a/vlan.c b/vlan.c
index 9201979a6d99f3f492a11beb296b2c78a09470ae..28e561b61dd2aa5523ecff3466bb21e7ed022f34 100644 (file)
--- a/vlan.c
+++ b/vlan.c
@@ -88,6 +88,10 @@ static void vlan_dev_cb(struct device_user *dep, enum device_event ev)
                vlan_dev_set_name(vldev, dep->dev);
                device_broadcast_event(&vldev->dev, ev);
                break;
+       case DEV_EVENT_TOPO_CHANGE:
+               /* Propagate topo changes */
+               device_broadcast_event(&vldev->dev, DEV_EVENT_TOPO_CHANGE);
+               break;
        default:
                break;
        }