aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gtphub.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2015-12-06 19:11:45 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2015-12-07 13:37:11 +0100
commitee07e4f75d1fc31dd6326e50535441a391c7de1e (patch)
tree850f8eb1880d7e237bdd1411e7d48d099f23595f /openbsc/src/gprs/gtphub.c
parentf6e4d082194e41c8a5b51a46c578921006496309 (diff)
gtphub: simplify/fix: one TEI mapping per tunnel.
Because the sender is known, one unique TEI per tunnel suffices to map the TEIs that the peers are sending to gtphub, instead of previously 4 (SGSN<->GGSN interaction on User and Ctrl plane, where each had an own unique TEI). Also, previously, a tunnel's endpoints should also have been checked against each other for TEI reuse, not only against the endpoints of other tunnels. This simplification fixes that problem for free. Thus simplify TEI reuse detection and improve VTY show readability and debugging. Adjust log and VTY output for tunnels. Adjust tests accordingly. Suggested-by: Holger Hans Peter Freyther <holger@moiji-mobile.com> Sponsored-by: On-Waves ehi
Diffstat (limited to 'openbsc/src/gprs/gtphub.c')
-rw-r--r--openbsc/src/gprs/gtphub.c78
1 files changed, 37 insertions, 41 deletions
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index 24d0c5829..0218924f0 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -995,9 +995,9 @@ static const char *gtphub_tunnel_side_str(struct gtphub_tunnel *tun,
APPEND("/%s", gsn_addr_to_str(&u->peer->peer_addr->addr));
}
- APPEND(" (TEI C %x=%x/U %x=%x)",
- c->tei_orig, c->tei_repl,
- u->tei_orig, u->tei_repl);
+ APPEND(" (TEI C=%x U=%x)",
+ c->tei_orig,
+ u->tei_orig);
return buf;
}
@@ -1008,6 +1008,7 @@ const char *gtphub_tunnel_str(struct gtphub_tunnel *tun)
int left = sizeof(buf);
int l;
+ APPEND("TEI=%x: ", tun->tei_repl);
APPEND("%s", gtphub_tunnel_side_str(tun, GTPH_SIDE_SGSN));
APPEND(" <-> %s", gtphub_tunnel_side_str(tun, GTPH_SIDE_GGSN));
@@ -1030,12 +1031,14 @@ int gtphub_tunnel_complete(struct gtphub_tunnel *tun)
{
if (!tun)
return 0;
+ if (!tun->tei_repl)
+ return 0;
int side_idx;
int plane_idx;
for_each_side_and_plane(side_idx, plane_idx) {
struct gtphub_tunnel_endpoint *te =
&tun->endpoint[side_idx][plane_idx];
- if (!(te->peer && te->tei_orig && te->tei_repl))
+ if (!(te->peer && te->tei_orig))
return 0;
}
return 1;
@@ -1212,29 +1215,33 @@ static struct gtphub_peer_port *gtphub_unmap_seq(struct gtp_packet_desc *p,
return nrm->origin;
}
-static int gtphub_check_mapped_tei(struct gtphub_tunnel_endpoint *new_te,
- struct gtphub_tunnel_endpoint *iterated_te,
+static int gtphub_check_mapped_tei(struct gtphub_tunnel *new_tun,
+ struct gtphub_tunnel *iterated_tun,
uint32_t *tei_min,
uint32_t *tei_max)
{
- if (!new_te->tei_repl)
+ if (!new_tun->tei_repl || !iterated_tun->tei_repl)
return 1;
- if (new_te->tei_repl != iterated_te->tei_repl)
+
+ *tei_min = (*tei_min < iterated_tun->tei_repl)? *tei_min : iterated_tun->tei_repl;
+ *tei_max = (*tei_max > iterated_tun->tei_repl)? *tei_max : iterated_tun->tei_repl;
+
+ if (new_tun->tei_repl != iterated_tun->tei_repl)
return 1;
- /* new_te->tei_repl is already taken. Try to find one out of the known
+ /* new_tun->tei_repl is already taken. Try to find one out of the known
* range. */
- LOG(LOGL_DEBUG, "TEI replacement %d already taken.\n", new_te->tei_repl);
+ LOG(LOGL_DEBUG, "TEI replacement %d already taken.\n", new_tun->tei_repl);
if ((*tei_max) < 0xffffffff) {
(*tei_max)++;
- new_te->tei_repl = *tei_max;
- LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_te->tei_repl);
+ new_tun->tei_repl = *tei_max;
+ LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
return 1;
} else if ((*tei_min) > 1) {
(*tei_min)--;
- new_te->tei_repl = *tei_min;
- LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_te->tei_repl);
+ new_tun->tei_repl = *tei_min;
+ LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
return 1;
}
@@ -1249,8 +1256,6 @@ static int gtphub_check_reused_teis(struct gtphub *hub,
uint32_t tei_max = 0;
int side_idx;
int plane_idx;
- int side_idx2;
- int plane_idx2;
struct gtphub_tunnel_endpoint *te;
struct gtphub_tunnel_endpoint *te2;
@@ -1303,23 +1308,14 @@ static int gtphub_check_reused_teis(struct gtphub *hub,
if (tun_continue)
continue;
- /* Check whether the mapped TEIs assigned to the endpoints are
- * used anywhere else. */
- for_each_side_and_plane(side_idx, plane_idx) {
- te = &tun->endpoint[side_idx][plane_idx];
- tei_min = (tei_min < te->tei_repl)? tei_min : te->tei_repl;
- tei_max = (tei_max > te->tei_repl)? tei_max : te->tei_repl;
-
- for_each_side_and_plane(side_idx2, plane_idx2) {
- te2 = &new_tun->endpoint[side_idx2][plane_idx2];
- if (!gtphub_check_mapped_tei(te2, te, &tei_min, &tei_max)) {
- LOG(LOGL_ERROR,
- "No mapped TEI is readily available."
- " Searching for holes between occupied"
- " TEIs not implemented.");
- return 0;
- }
- }
+ /* Check whether the mapped TEI is already used by another
+ * tunnel. */
+ if (!gtphub_check_mapped_tei(new_tun, tun, &tei_min, &tei_max)) {
+ LOG(LOGL_ERROR,
+ "No mapped TEI is readily available."
+ " Searching for holes between occupied"
+ " TEIs not implemented.");
+ return 0;
}
}
@@ -1350,7 +1346,7 @@ static struct gtphub_tunnel_endpoint *gtphub_unmap_tei(struct gtphub *hub,
&tun->endpoint[p->side_idx][p->plane_idx];
struct gtphub_tunnel_endpoint *te_to =
&tun->endpoint[other_side][p->plane_idx];
- if ((te_to->tei_repl == p->header_tei_rx)
+ if ((tun->tei_repl == p->header_tei_rx)
&& te_from->peer
&& gsn_addr_same(&te_from->peer->peer_addr->addr,
&from->peer_addr->addr)) {
@@ -1453,6 +1449,10 @@ static int gtphub_handle_create_pdp_ctx(struct gtphub *hub,
/* A new tunnel. */
p->tun = tun = gtphub_tunnel_new();
+
+ /* Create TEI mapping */
+ tun->tei_repl = nr_pool_next(&hub->tei_pool);
+
llist_add(&tun->entry, &hub->tunnels);
gtphub_tunnel_refresh(hub, tun, p->timestamp);
/* The endpoint peers on this side (SGSN) will be set from IEs
@@ -1471,8 +1471,7 @@ static int gtphub_handle_create_pdp_ctx(struct gtphub *hub,
* TEI and be available in tun (== p->tun). Just fill in the
* GSN Addresses below.*/
OSMO_ASSERT(tun);
- OSMO_ASSERT(tun->endpoint[other_side_idx(p->side_idx)][GTPH_PLANE_CTRL].tei_repl
- == p->header_tei_rx);
+ OSMO_ASSERT(tun->tei_repl == p->header_tei_rx);
OSMO_ASSERT(to_ctrl);
}
@@ -1555,12 +1554,9 @@ static int gtphub_handle_create_pdp_ctx(struct gtphub *hub,
}
if (tei_from_ie) {
- /* Create TEI mapping and replace in GTP packet IE */
- uint32_t mapped_tei = nr_pool_next(&hub->tei_pool);
-
+ /* Replace TEI in GTP packet IE */
tun->endpoint[side_idx][plane_idx].tei_orig = tei_from_ie;
- tun->endpoint[side_idx][plane_idx].tei_repl = mapped_tei;
- p->ie[ie_idx]->tv4.v = hton32(mapped_tei);
+ p->ie[ie_idx]->tv4.v = hton32(tun->tei_repl);
if (!gtphub_check_reused_teis(hub, tun)) {
/* It's highly unlikely that all TEIs are