From: Helmut Schaa Date: Thu, 20 Mar 2014 15:26:23 +0000 (+0100) Subject: netifd: Reload proto on topology change X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3d317e90f15eec480b23f4dcddb841c292bef690;p=oweals%2Fnetifd.git netifd: Reload proto on topology change 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 --- diff --git a/bridge.c b/bridge.c index 147fe0a..6baef29 100644 --- 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: diff --git a/device.h b/device.h index dd57927..e71027e 100644 --- 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 }; diff --git a/interface.c b/interface.c index 4a3a725..fa8e55e 100644 --- a/interface.c +++ b/interface.c @@ -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(); diff --git a/proto-shell.c b/proto-shell.c index 9041045..de1b084 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -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); diff --git a/proto-static.c b/proto-static.c index 77a536a..b492d92 100644 --- a/proto-static.c +++ b/proto-static.c @@ -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 64be308..3a7b2a8 100644 --- 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 e402a91..e7d84ac 100644 --- 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 { diff --git a/scripts/netifd-proto.sh b/scripts/netifd-proto.sh index 7f08b1d..ce316c4 100644 --- a/scripts/netifd-proto.sh +++ b/scripts/netifd-proto.sh @@ -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 9201979..28e561b 100644 --- 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; }