Skip to content
Snippets Groups Projects
config.c 33.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Anjan Chanda's avatar
    Anjan Chanda committed
    	}
    
    	uci_foreach_element(&pkg->sections, e) {
    		struct uci_section *s = uci_to_section(e);
    		struct uci_element *x, *tmp;
    		struct uci_option *op;
    
    		if (strcmp(s->type, section))
    			continue;
    
    		/* iter through matched 'section' for the 'option' */
    		uci_foreach_element_safe(&s->options, tmp, x) {
    			if (strcmp(x->name, option))
    				continue;
    
    			op = uci_to_option(x);
    			if (op->type == UCI_TYPE_LIST) {
    				uci_foreach_element(&op->v.list, x) {
    					if (!strncmp(x->name, value, len)) {
    						if (!add)
    							config_update_entry(ctx,
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    								pkg, s,
    								option, 0,
    								value, len);
    
    Anjan Chanda's avatar
    Anjan Chanda committed
    
    						goto out_exit;
    					}
    				}
    				/* add new exclude at end of list */
    				if (add)
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    					config_update_entry(ctx, pkg, s, option,
    							1, value, len);
    
    Anjan Chanda's avatar
    Anjan Chanda committed
    
    				goto out_exit;
    			}
    		}
    		/* 'option' name not present in 'section'
    		 * Create a new one at end of 'section'.
    		 */
    		if (add)
    			config_update_entry(ctx, pkg, s, option, 1, value, len);
    
    		goto out_exit;
    	}
    out_exit:
    	uci_free_context(ctx);
    	return 0;
    }
    
    int config_update2(const char *confname, struct agent_config *cfg,
    		const char *section_type,
    		const char *match_option,
    		const char *match_option_value,
    		const char *option,
    		int add,
    		void *value, int len)
    {
    	struct uci_context *ctx = NULL;
    	struct uci_package *pkg = NULL;
    	struct uci_element *e;
    
    	ctx = uci_alloc_context();
    	if (ctx && uci_load(ctx, confname, &pkg) != UCI_OK) {
    		dbg("config file '%s' not found!\n", confname);
    		free(ctx);
    		return -1;
    	}
    
    	uci_foreach_element(&pkg->sections, e) {
    		struct uci_section *s = uci_to_section(e);
    		struct uci_element *x, *tmp;
    		struct uci_option *op;
    		const char *optstring;
    
    		if (strcmp(s->type, section_type))
    			continue;
    
    		if (match_option && match_option_value) {
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    			optstring = uci_lookup_option_string(ctx, s,
    				match_option);
    
    Anjan Chanda's avatar
    Anjan Chanda committed
    			if (!optstring || strcmp(optstring, match_option_value))
    				continue;
    		}
    
    		/* iter through matched 'section' for the 'option' */
    		uci_foreach_element_safe(&s->options, tmp, x) {
    			if (strcmp(x->name, option))
    				continue;
    
    			op = uci_to_option(x);
    			if (op->type == UCI_TYPE_LIST) {
    				uci_foreach_element(&op->v.list, x) {
    					if (!strncmp(x->name, value, len)) {
    						if (!add) {
    							config_update_entry(ctx,
    								pkg, s, option,
    								0, value, len);
    						}
    
    						goto out_exit;
    					}
    				}
    				/* add new 'option' at end of list */
    				if (add) {
    					config_update_entry(ctx, pkg, s, option,
    								1, value, len);
    				}
    
    				goto out_exit;
    			}
    		}
    		/* 'option' name not present in 'section'
    		 * Create a new one at end of 'section'.
    		 */
    		if (add)
    			config_update_entry(ctx, pkg, s, option,
    							1, value, len);
    
    		goto out_exit;
    	}
    out_exit:
    	uci_free_context(ctx);
    	return 0;
    }
    
    
    #if 0
    struct config uci_config = {
    	.name = "uci",
    	.priv = uci_ctx;
    	.get = uci_get_config,
    	.set = uci_set_config,
    	.init = uci_setup,
    	.exit = uci_exit,
    };
    
    #define priv_get_config(priv)	container_of(priv, struct config, priv)
    
    void register_config(struct config *c)
    {
    	static struct uci_context *ctx;
    	static struct uci_package *pkg;
    	struct uci_element *e;
    	int ret = 0;
    
    	if (uci_ctx)
    		return priv_get_config(uci_ctx);
    
    	ctx = uci_alloc_context();
    	if (ctx) {
    		uci_ctx = ctx;
    		memcpy(c, &uci_config, sizeof(*cfg));
    	}
    	if (uci_load(ctx, "wifiagent", &pkg))
    		return -1;
    
    	uci_foreach_element(&pkg->sections, e) {
    		struct uci_section *s = uci_to_section(e);
    		const char *option_val;
    
    		if (strcmp(s->type, "wifiagent"))
    			continue;
    
    		option_val = uci_lookup_option_string(ctx, s, name);
    		if (option_val)
    			sprintf(val, "%s", option_val);
    		else
    			ret = -1;
    	}
    	uci_free_context(ctx);
    	return ret;
    
    }
    #endif
    
    static int agent_config_get_wifi_agent(struct agent_config *a,
    
    						struct uci_section *s)
    {
    	enum {
    		A_ENABLED,
    
    		A_PROFILE,
    
    		NUM_POLICIES
    	};
    	const struct uci_parse_option opts[] = {
    		{ .name = "enabled", .type = UCI_TYPE_STRING },
    
    		{ .name = "debug", .type = UCI_TYPE_STRING },
    
    		{ .name = "profile", .type = UCI_TYPE_STRING },
    
    	};
    	struct uci_option *tb[NUM_POLICIES];
    
    	uci_parse_section(s, opts, NUM_POLICIES, tb);
    
    	if (tb[A_ENABLED])
    		a->enabled = atoi(tb[A_ENABLED]->v.string) == 1 ? true : false;
    
    
    	if (tb[A_DEBUG]) {
    		a->debug_level = atoi(tb[A_DEBUG]->v.string);
    		if (verbose < a->debug_level)
    			verbose = a->debug_level;
    	}
    
    
    	if (tb[A_PROFILE])
    		a->profile = atoi(tb[A_PROFILE]->v.string);
    
    
    static int agent_config_get_bk_iface(struct agent_config *a,
    
    						struct uci_section *s)
    {
    	enum {
    		BK_IFNAME,
    
    		BK_BAND,
    
    		BK_ENABLED,
    		BK_ONBOARDED,
    		NUM_POLICIES
    	};
    	const struct uci_parse_option opts[] = {
    		{ .name = "ifname", .type = UCI_TYPE_STRING },
    
    		{ .name = "band", .type = UCI_TYPE_STRING },
    
    		{ .name = "enabled", .type = UCI_TYPE_STRING },
    		{ .name = "onboarded", .type = UCI_TYPE_STRING }
    	};
    	struct uci_option *tb[NUM_POLICIES];
    	struct netif_bkcfg *bk;
    	const char *ifname;
    
    	uci_parse_section(s, opts, NUM_POLICIES, tb);
    
    	if (tb[BK_IFNAME]) {
    		ifname = tb[BK_IFNAME]->v.string;
    		bk = get_netif_bkcfg_by_name(a, ifname);
    		if (!bk) {
    			bk = create_backhaul_iface_config(a, ifname);
    			if (!bk) {
    				warn("%s: OOM!\n", __func__);
    				return -1;
    			}
    		} else {
    			warn("Duplicate 'bk-iface %s' config!! ignore\n",
    					ifname);
    		}
    	} else {
    		warn("No ifname in bk-iface section!\n");
    		return -1;
    	}
    
    	if (tb[BK_ENABLED])
    		bk->enabled = atoi(tb[BK_ENABLED]->v.string);
    
    	if (tb[BK_ONBOARDED])
    		bk->onboarded = atoi(tb[BK_ONBOARDED]->v.string);
    
    
    	if (tb[BK_BAND]) {
    		int band = atoi(tb[BK_BAND]->v.string);
    
    		if (band == 2)
    			bk->band = BAND_2;
    		else if (band == 5)
    			bk->band = BAND_5;
    	}
    
    
    static int agent_config_get_fh_iface(struct agent_config *a,
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    		struct uci_section *s)
    
    		FH_BAND,
    
    		FH_STEER,
    		FH_EXCLUDE,
    		FH_EXCLUDE_BTM,
    		FH_ASSOC_CTRL,
    		FH_BTM_RETRY,
    		FH_BTM_RETRY_SECS,
    		FH_FLBK_LEGACY,
    		FH_STEER_LEGACY_RASSOC_SECS,
    		FH_STEER_LEGACY_RETRY_SECS,
    		FH_ASSOC_CTRL_SECS,
    		NUM_POLICIES,
    	};
    	const struct uci_parse_option opts[] = {
    		{ .name = "ifname", .type = UCI_TYPE_STRING },
    
    		{ .name = "band", .type = UCI_TYPE_STRING },
    
    		{ .name = "steer", .type = UCI_TYPE_LIST },
    		{ .name = "exclude", .type = UCI_TYPE_LIST },
    		{ .name = "exclude_btm", .type = UCI_TYPE_LIST },
    		{ .name = "assoc_ctrl", .type = UCI_TYPE_LIST },
    
    		{ .name = "btm_retry", .type = UCI_TYPE_STRING },
    		{ .name = "btm_retry_secs", .type = UCI_TYPE_STRING },
    		{ .name = "fallback_legacy", .type = UCI_TYPE_STRING },
    		{ .name = "steer_legacy_reassoc_secs", .type = UCI_TYPE_STRING },
    		{ .name = "steer_legacy_retry_secs", .type = UCI_TYPE_STRING },
    		{ .name = "assoc_ctrl_secs", .type = UCI_TYPE_STRING }
    	};
    	struct uci_option *tb[NUM_POLICIES];
    	struct netif_fhcfg *fh;
    
    	uci_parse_section(s, opts, NUM_POLICIES, tb);
    
    	if (tb[FH_IFNAME]) {
    
    		const char *ifname;
    
    
    		ifname = tb[FH_IFNAME]->v.string;
    
    		fh = get_netif_fhcfg_by_name(a, ifname);
    		if (!fh) {
    			fh = create_fronthaul_iface_config(a, ifname);
    			if (!fh) {
    				warn("%s: OOM!\n", __func__);
    				return -1;
    			}
    		} else {
    
    			clean_steer_btm_excl(fh);
    			clean_steer_excl(fh);
    
    			warn("Duplicate 'fh-iface %s' config!! ignore\n",
    					ifname);
    		}
    	} else {
    		warn("No ifname in fh-iface section!\n");
    		return -1;
    	}
    
    
    	if (tb[FH_BAND]) {
    		int band = atoi(tb[FH_BAND]->v.string);
    
    		if (band == 2)
    			fh->band = BAND_2;
    		else if (band == 5)
    			fh->band = BAND_5;
    	}
    
    
    	if (tb[FH_STEER]) {
    		struct uci_element *xi;
    
    		dbg("Steer: param: ");
    		uci_foreach_element(&tb[FH_STEER]->v.list, xi) {
    			struct steer_policy *p = NULL;
    			struct steer_rule *r;
    
    			dbg("%s ", xi->name);
    			p = get_steer_policy_by_name(fh, xi->name);
    			if (!p) {
    				/* TODO? */
    				dbg("TODO!! steer before ifname\n");
    				continue;
    			}
    			p->enabled = true;
    			r = get_steer_rule_by_name(xi->name);
    			if (r)
    				r->enabled = true;
    		}
    		dbg("\n");
    	}
    
    	if (tb[FH_EXCLUDE]) {
    		struct uci_element *xi;
    
    		dbg("Steer: exclude: ");
    		uci_foreach_element(&tb[FH_EXCLUDE]->v.list, xi) {
    			dbg("%s ", xi->name);
    			stax_add_entry(&fh->steer_excludelist, xi->name);
    		}
    		dbg("\n");
    	}
    
    	if (tb[FH_EXCLUDE_BTM]) {
    		struct uci_element *xi;
    
    		dbg("Steer: exclude_btm: ");
    		uci_foreach_element(&tb[FH_EXCLUDE_BTM]->v.list, xi) {
    			dbg("%s ", xi->name);
    			stax_add_entry(&fh->steer_btm_excludelist, xi->name);
    		}
    		dbg("\n");
    	}
    
    	if (tb[FH_BTM_RETRY])
    		fh->steer_btm_retry = atoi(tb[FH_BTM_RETRY]->v.string);
    
    	if (tb[FH_BTM_RETRY_SECS])
    		fh->steer_btm_retry_secs = atoi(tb[FH_BTM_RETRY_SECS]->v.string);
    
    	if (tb[FH_FLBK_LEGACY])
    		fh->fallback_legacy = atoi(tb[FH_FLBK_LEGACY]->v.string);
    
    	if (tb[FH_STEER_LEGACY_RASSOC_SECS])
    		fh->steer_legacy_reassoc_secs =
    				atoi(tb[FH_STEER_LEGACY_RASSOC_SECS]->v.string);
    
    	if (tb[FH_STEER_LEGACY_RETRY_SECS])
    		fh->steer_legacy_retry_secs =
    				atoi(tb[FH_STEER_LEGACY_RETRY_SECS]->v.string);
    
    	if (tb[FH_ASSOC_CTRL_SECS])
    		fh->assoc_control_time =
    				atoi(tb[FH_ASSOC_CTRL_SECS]->v.string);
    
    	return 0;
    }
    
    
    static int agent_config_get_steer_param(struct agent_config *a,
    		struct uci_section *s)
    
    {
    	struct steer_rule *r;
    
    	dbg("Steer-param: %s\n", s->e.name);
    	r = get_steer_rule_by_name(s->e.name);
    	if (!r)
    		return -1;
    
    	dbg("Rule to handle steer-param '%s' available\n", s->e.name);
    	r->config(r, a, s);
    
    	return 0;
    }
    
    
    int agent_config_reload(struct agent_config *cfg)
    
    {
    	struct uci_context *ctx;
    	struct uci_package *pkg;
    	struct uci_element *e;
    
    
    	cfg->enabled = false;
    	cfg->runfreq = AGENT_RUN_AUTO;
    
    
    	ctx = uci_alloc_context();
    	if (!ctx)
    		return -1;
    
    	if (uci_load(ctx, "agent", &pkg)) {
    		uci_free_context(ctx);
    		return -1;
    	}
    
    	uci_foreach_element(&pkg->sections, e) {
    		struct uci_section *s = uci_to_section(e);
    
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    		if (!strcmp(s->type, "wifiagent"))
    
    			agent_config_get_wifi_agent(cfg, s);
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    		else if (!strcmp(s->type, "fh-iface"))
    
    			agent_config_get_fh_iface(cfg, s);
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    		else if (!strcmp(s->type, "bk-iface"))
    
    			agent_config_get_bk_iface(cfg, s);
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    		else if (!strcmp(s->type, "steer"))
    
    			agent_config_get_steer_param(cfg, s);
    
    Jakob Olsson's avatar
    Jakob Olsson committed
    }
    
    
    int agent_config_init(struct agent_config *cfg)
    {
    	INIT_LIST_HEAD(&cfg->fhlist);
    	INIT_LIST_HEAD(&cfg->bklist);
    
    	agent_config_reload(cfg);
    	return 0;
    }
    
    void clean_bk(struct netif_bkcfg *p)
    {
    	list_del(&p->list);
    	free(p);
    }
    
    int clean_all_bk(struct agent_config *cfg)
    {
    	struct netif_bkcfg *p, *tmp;
    
    	list_for_each_entry_safe(p, tmp, &cfg->bklist, list)
    		clean_bk(p);
    
    	return 0;
    }
    
    void clean_fh(struct netif_fhcfg *p)
    {
    	clean_steer_btm_excl(p);
    	clean_steer_excl(p);
    	list_del(&p->list);
    	free(p);
    }
    
    int clean_all_fh(struct agent_config *cfg)
    {
    	struct netif_fhcfg *p, *tmp;
    
    	list_for_each_entry_safe(p, tmp, &cfg->fhlist, list)
    		clean_fh(p);
    
    	return 0;
    }
    
    int agent_config_clean(struct agent_config *cfg)
    {
    	clean_all_fh(cfg);
    	clean_all_bk(cfg);
    
    	return 0;
    }