diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-10-08 22:08:29 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-10-08 22:21:46 +0800 |
commit | 0bd60f331760222f18a425fae727cff0592e5bd0 (patch) | |
tree | 9c0b00080583a3e4922c021a981f23e8a0d38857 /openbsc | |
parent | fad0753b3435c6ce13536188b74f08c76309a1be (diff) |
nat: Allow a BSC to have multiple LACs
Make it possible that one BSC is serving multiple
cells. Introduce a list of lacs, add functions to
manipulate the lists. The current test cases for
paging by lac continue to work.
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 14 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 4 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat_utils.c | 52 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat_vty.c | 45 | ||||
-rw-r--r-- | openbsc/tests/bsc-nat/bsc_nat_test.c | 26 |
5 files changed, 112 insertions, 29 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index bb1b2ac52..4983af56d 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -112,7 +112,6 @@ struct bsc_config { struct llist_head entry; char *token; - unsigned int lac; int nr; char *description; @@ -126,6 +125,13 @@ struct bsc_config { struct bsc_nat *nat; struct bsc_config_stats stats; + + struct llist_head lac_list; +}; + +struct bsc_lac_entry { + struct llist_head entry; + uint16_t lac; }; /** @@ -229,8 +235,12 @@ struct bsc_nat { }; /* create and init the structures */ -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac); +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token); struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num); +void bsc_config_add_lac(struct bsc_config *cfg, int lac); +void bsc_config_del_lac(struct bsc_config *cfg, int lac); +int bsc_config_handles_lac(struct bsc_config *cfg, int lac); + struct bsc_nat *bsc_nat_alloc(void); struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat); void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip); diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index 48407b9a8..f5eca808d 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -753,8 +753,8 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc bsc->authenticated = 1; bsc->cfg = conf; bsc_del_timer(&bsc->id_timeout); - LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d on fd %d\n", - conf->nr, conf->lac, bsc->write_queue.bfd.fd); + LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d on fd %d\n", + conf->nr, bsc->write_queue.bfd.fd); start_ping_pong(bsc); return; } diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c index 44443d26e..e11b48c31 100644 --- a/openbsc/src/nat/bsc_nat_utils.c +++ b/openbsc/src/nat/bsc_nat_utils.c @@ -116,21 +116,22 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat) return con; } -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac) +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token) { struct bsc_config *conf = talloc_zero(nat, struct bsc_config); if (!conf) return NULL; conf->token = talloc_strdup(conf, token); - conf->lac = lac; conf->nr = nat->num_bsc; conf->nat = nat; + INIT_LLIST_HEAD(&conf->lac_list); + llist_add_tail(&conf->entry, &nat->bsc_configs); ++nat->num_bsc; - conf->stats.ctrg = rate_ctr_group_alloc(conf, &bsc_cfg_ctrg_desc, conf->lac); + conf->stats.ctrg = rate_ctr_group_alloc(conf, &bsc_cfg_ctrg_desc, conf->nr); if (!conf->stats.ctrg) { talloc_free(conf); return NULL; @@ -139,6 +140,47 @@ struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsi return conf; } +void bsc_config_add_lac(struct bsc_config *cfg, int _lac) +{ + struct bsc_lac_entry *lac; + + llist_for_each_entry(lac, &cfg->lac_list, entry) + if (lac->lac == _lac) + return; + + lac = talloc_zero(cfg, struct bsc_lac_entry); + if (!lac) { + LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n"); + return; + } + + lac->lac = _lac; + llist_add_tail(&lac->entry, &cfg->lac_list); +} + +void bsc_config_del_lac(struct bsc_config *cfg, int _lac) +{ + struct bsc_lac_entry *lac; + + llist_for_each_entry(lac, &cfg->lac_list, entry) + if (lac->lac == _lac) { + llist_del(&lac->entry); + talloc_free(lac); + return; + } +} + +int bsc_config_handles_lac(struct bsc_config *cfg, int lac_nr) +{ + struct bsc_lac_entry *entry; + + llist_for_each_entry(entry, &cfg->lac_list, entry) + if (entry->lac == lac_nr) + return 1; + + return 0; +} + void sccp_connection_destroy(struct sccp_connections *conn) { LOGP(DNAT, LOGL_DEBUG, "Destroy 0x%x <-> 0x%x mapping for con %p\n", @@ -188,7 +230,9 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, i llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) { if (!bsc->cfg) continue; - if (!bsc->authenticated || _lac != bsc->cfg->lac) + if (!bsc->authenticated) + continue; + if (!bsc_config_handles_lac(bsc->cfg, _lac)) continue; return bsc; diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c index 0da686dc3..1dbc75569 100644 --- a/openbsc/src/nat/bsc_nat_vty.c +++ b/openbsc/src/nat/bsc_nat_vty.c @@ -86,11 +86,18 @@ static int config_write_nat(struct vty *vty) return CMD_SUCCESS; } +static void dump_lac(struct vty *vty, struct bsc_config *cfg) +{ + struct bsc_lac_entry *lac; + llist_for_each_entry(lac, &cfg->lac_list, entry) + vty_out(vty, " location_area_code %u%s", lac->lac, VTY_NEWLINE); +} + static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc) { vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE); vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE); - vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE); + dump_lac(vty, bsc); vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE); if (bsc->description) vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE); @@ -115,9 +122,8 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", vty_out(vty, "Listing all open SCCP connections%s", VTY_NEWLINE); llist_for_each_entry(con, &_nat->sccp_connections, list_entry) { - vty_out(vty, "For BSC Nr: %d lac: %d; BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s", + vty_out(vty, "For BSC Nr: %d BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s", con->bsc->cfg ? con->bsc->cfg->nr : -1, - con->bsc->cfg ? con->bsc->cfg->lac : -1, sccp_src_ref_to_int(&con->real_ref), sccp_src_ref_to_int(&con->patched_ref), con->has_remote_ref, @@ -139,9 +145,8 @@ DEFUN(show_bsc, show_bsc_cmd, "show bsc connections", llist_for_each_entry(con, &_nat->bsc_connections, list_entry) { getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len); - vty_out(vty, "BSC nr: %d lac: %d auth: %d fd: %d peername: %s%s", + vty_out(vty, "BSC nr: %d auth: %d fd: %d peername: %s%s", con->cfg ? con->cfg->nr : -1, - con->cfg ? con->cfg->lac : -1, con->authenticated, con->write_queue.bfd.fd, inet_ntoa(sock.sin_addr), VTY_NEWLINE); } @@ -178,8 +183,8 @@ DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config", { struct bsc_config *conf; llist_for_each_entry(conf, &_nat->bsc_configs, entry) { - vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s", - conf->token, conf->lac, conf->nr, VTY_NEWLINE); + vty_out(vty, "BSC token: '%s' nr: %u%s", + conf->token, conf->nr, VTY_NEWLINE); if (conf->acc_lst_name) vty_out(vty, " access-list: %s%s", conf->acc_lst_name, VTY_NEWLINE); @@ -215,8 +220,8 @@ static void dump_stat_bsc(struct vty *vty, struct bsc_config *conf) int connected = 0; struct bsc_connection *con; - vty_out(vty, " BSC lac: %d nr: %d%s", - conf->lac, conf->nr, VTY_NEWLINE); + vty_out(vty, " BSC nr: %d%s", + conf->nr, VTY_NEWLINE); vty_out_rate_ctr_group(vty, " ", conf->stats.ctrg); llist_for_each_entry(con, &conf->nat->bsc_connections, list_entry) { @@ -264,7 +269,7 @@ DEFUN(show_stats_lac, dump_stat_total(vty, _nat); llist_for_each_entry(conf, &_nat->bsc_configs, entry) { - if (conf->lac != lac) + if (!bsc_config_handles_lac(conf, lac)) continue; dump_stat_bsc(vty, conf); } @@ -406,7 +411,7 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure") return CMD_WARNING; } else if (bsc_nr == _nat->num_bsc) { /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown", 0); + bsc = bsc_config_alloc(_nat, "unknown"); } else bsc = bsc_config_num(_nat, bsc_nr); @@ -445,17 +450,30 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>", /* verify that the LACs are unique */ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) { - if (tmp->lac == lac) { + if (bsc_config_handles_lac(tmp, lac)) { vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE); return CMD_ERR_INCOMPLETE; } } - conf->lac = lac; + bsc_config_add_lac(conf, lac); + + return CMD_SUCCESS; +} + +DEFUN(cfg_bsc_no_lac, cfg_bsc_no_lac_cmd, + "no location_area_code <0-65535>", + NO_STR "Set the Location Area Code (LAC) of this BSC") +{ + int lac = atoi(argv[0]); + struct bsc_config *conf = vty->index; + bsc_config_del_lac(conf, lac); return CMD_SUCCESS; } + + DEFUN(cfg_lst_imsi_allow, cfg_lst_imsi_allow_cmd, "access-list NAME imsi-allow [REGEXP]", @@ -638,6 +656,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_BSC_NODE, &ournode_end_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd); + install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_desc_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_acc_lst_name_cmd); diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index 4ab44de2f..f82b4db5f 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -287,7 +287,12 @@ static void test_contrack() fprintf(stderr, "Testing connection tracking.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = bsc_config_alloc(nat, "foo", 23); + con->cfg = bsc_config_alloc(nat, "foo"); + bsc_config_add_lac(con->cfg, 23); + bsc_config_add_lac(con->cfg, 49); + bsc_config_add_lac(con->cfg, 42); + bsc_config_del_lac(con->cfg, 49); + bsc_config_add_lac(con->cfg, 1111); msg = msgb_alloc(4096, "test"); /* 1.) create a connection */ @@ -383,15 +388,16 @@ static void test_paging(void) struct bsc_nat *nat; struct bsc_connection *con; struct bsc_nat_parsed *parsed; - struct bsc_config cfg; + struct bsc_config *cfg; struct msgb *msg; fprintf(stderr, "Testing paging by lac.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = &cfg; - cfg.lac = 23; + cfg = bsc_config_alloc(nat, "unknown"); + con->cfg = cfg; + bsc_config_add_lac(cfg, 23); con->authenticated = 1; llist_add(&con->list_entry, &nat->bsc_connections); msg = msgb_alloc(4096, "test"); @@ -413,7 +419,8 @@ static void test_paging(void) talloc_free(parsed); /* Test by finding it */ - cfg.lac = 8213; + bsc_config_del_lac(cfg, 23); + bsc_config_add_lac(cfg, 8213); copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd)); parsed = bsc_nat_parse(msg); if (bsc_nat_find_bsc(nat, msg, &lac) != con) { @@ -439,7 +446,8 @@ static void test_mgcp_ass_tracking(void) struct bsc_endpoint, 33); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo", 2323); + bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x1a; con.bsc = bsc; @@ -668,7 +676,8 @@ static void test_cr_filter() struct bsc_nat *nat = bsc_nat_alloc(); struct bsc_connection *bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo", 1234); + bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc_config_add_lac(bsc->cfg, 1234); bsc->cfg->acc_lst_name = "bsc"; nat->acc_lst_name = "nat"; @@ -728,7 +737,8 @@ static void test_dt_filter() struct bsc_connection *bsc = bsc_connection_alloc(nat); struct sccp_connections *con = talloc_zero(0, struct sccp_connections); - bsc->cfg = bsc_config_alloc(nat, "foo", 23); + bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc_config_add_lac(bsc->cfg, 23); con->bsc = bsc; msgb_reset(msg); |