Hoernchen has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmo-abis/+/14743


Change subject: add ipa pingp/pong keepalive for OML/RSL links between bts and 
bsc
......................................................................

add ipa pingp/pong keepalive for OML/RSL links between bts and bsc

Change-Id: I30e3bd601e55355aaf738ee2f2c44c1ec2c46c6a
---
M include/osmocom/abis/e1_input.h
M src/e1_input_vty.c
M src/input/ipaccess.c
3 files changed, 186 insertions(+), 11 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/43/14743/1

diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index e6d5154..4459392 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -187,11 +187,14 @@
        char *sock_path;
        struct rate_ctr_group *rate_ctr;

-       /* keepalive configuration */
+       /* tcp keepalive configuration */
        int keepalive_num_probes; /* 0: disable, num, or E1INP_USE_DEFAULT */
        int keepalive_idle_timeout; /* secs, or E1INP_USE_DEFAULT */
        int keepalive_probe_interval; /* secs or E1INP_USE_DEFAULT */

+       /* ipa ping/pong keepalive params */
+       struct ipa_keepalive_params* ipa_kap;
+
        /* array of timestlots */
        struct e1inp_ts ts[NUM_E1_TS];
        unsigned int num_ts;
diff --git a/src/e1_input_vty.c b/src/e1_input_vty.c
index d81c859..3c6a268 100644
--- a/src/e1_input_vty.c
+++ b/src/e1_input_vty.c
@@ -38,6 +38,7 @@
 #include <osmocom/vty/telnet_interface.h>

 #include <osmocom/abis/e1_input.h>
+#include <osmocom/abis/ipa.h>

 /* CONFIG */

@@ -169,6 +170,40 @@
        return set_keepalive_params(vty, atoi(argv[0]), 0, 0, 0);
 }

+DEFUN(cfg_e1line_ipakeepalive, cfg_e1_line_ipakeepalive_cmd,
+       "e1_line <0-255> ipakeepalive <0-300> <1-300>",
+       E1_LINE_HELP "Enable IPA PING/PONG keepalive\n"
+       "Idle interval in seconds before probes are sent, 0 disables 
keepalive\n"
+       "Time to wait for PONG response\n")
+{
+       int e1_nr = atoi(argv[0]);
+       int interval = atoi(argv[1]);
+       int waittime = atoi(argv[2]);
+       struct e1inp_line *line = e1inp_line_find(e1_nr);
+
+       if (!line) {
+               vty_out(vty, "%% Line %d doesn't exist%s", e1_nr, VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+       if(strcmp(line->driver->name, "ipa") != 0){
+               vty_out(vty, "%% Line %d doesn't use the ipa driver%s", e1_nr, 
VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       if (!line->driver->has_keepalive) {
+               vty_out(vty, "%% Driver '%s' does not support keep alive%s",
+               line->driver->name, VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       if(interval){
+               line->ipa_kap = talloc_zero(line, struct ipa_keepalive_params);
+               line->ipa_kap->wait_for_resp = waittime;
+               line->ipa_kap->interval = interval;
+       }
+       return CMD_SUCCESS;
+}
+
 DEFUN(cfg_e1line_name, cfg_e1_line_name_cmd,
        "e1_line <0-255> name .LINE",
        E1_LINE_HELP "Set name for this line\n" "Human readable name\n")
@@ -242,7 +277,10 @@
                                line->keepalive_num_probes,
                                line->keepalive_probe_interval,
                                VTY_NEWLINE);
-
+               if (line->ipa_kap)
+                       vty_out(vty, " e1_line %u ipakeepalive %d %d%s", 
line->num,
+                                       line->ipa_kap->interval, 
line->ipa_kap->wait_for_resp,
+                                       VTY_NEWLINE);
        }

        const char *ipa_bind = e1inp_ipa_get_bind_addr();
@@ -398,6 +436,7 @@
        install_element(L_E1INP_NODE, &cfg_e1_line_keepalive_cmd);
        install_element(L_E1INP_NODE, &cfg_e1_line_keepalive_params_cmd);
        install_element(L_E1INP_NODE, &cfg_e1_line_no_keepalive_cmd);
+       install_element(L_E1INP_NODE, &cfg_e1_line_ipakeepalive_cmd);

        install_element(L_E1INP_NODE, &cfg_ipa_bind_cmd);

diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index fb6ad10..b2b6a6b 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -59,15 +59,28 @@
 #define DEFAULT_TCP_KEEPALIVE_INTERVAL     3
 #define DEFAULT_TCP_KEEPALIVE_RETRY_COUNT  10

+#define ka_fsm_for_ts(ipaline,ofd) (ipaline->ka_fsm[ofd->priv_nr-1])
+
+struct ipaccess_line {
+    int line_already_initialized;
+    struct osmo_fsm_inst* ka_fsm[NUM_E1_TS];
+};
+
 static int ipaccess_drop(struct osmo_fd *bfd, struct e1inp_line *line)
 {
        int ret = 1;
        struct e1inp_ts *e1i_ts;
+       struct ipaccess_line *il = line->driver_data;
+       struct osmo_fsm_inst* f = ka_fsm_for_ts(il, bfd);
+
        if (bfd->priv_nr == E1INP_SIGN_OML)
                e1i_ts = e1inp_line_ipa_oml_ts(line);
        else
                e1i_ts = e1inp_line_ipa_rsl_ts(line, bfd->priv_nr - 
E1INP_SIGN_RSL);

+       if(f)
+               ipa_keepalive_fsm_stop(f);
+
        /* Error case: we did not see any ID_RESP yet for this socket. */
        if (bfd->fd != -1) {
                LOGP(DLINP, LOGL_ERROR, "Forcing socket shutdown with "
@@ -87,6 +100,29 @@
        return ret;
 }

+static void ipa_bsc_keepalive_write_server_cb(struct osmo_fsm_inst *fi, void 
*conn, struct msgb *msg){
+       struct osmo_fd *bfd = (struct osmo_fd *)conn;
+       int ret = 0;
+
+       ret = send(bfd->fd, msg->data, msg->len, 0);
+       msgb_free(msg);
+}
+
+static int ipa_bsc_keepalive_timeout_cb(struct osmo_fsm_inst *fi, void *data){
+       struct osmo_fd *bfd = (struct osmo_fd *)data;
+
+       if (bfd->fd == -1)
+               return 1;
+
+       struct e1inp_line *line = (struct e1inp_line *) bfd->data;
+       struct ipaccess_line *il = line->driver_data;
+
+       ipaccess_drop(bfd, line);
+       /* fsm will free itself upon returning */
+       ka_fsm_for_ts(il, bfd) = NULL;
+       return 1;
+}
+
 /* Returns -1 on error, and 0 or 1 on success. If -1 or 1 is returned, line has
  * been released and should not be used anymore by the caller. */
 static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
@@ -98,6 +134,11 @@
        struct e1inp_sign_link *sign_link;
        char *unitid;
        int len, ret;
+       struct ipaccess_line *il = line->driver_data;
+
+       /* peek the pong for our keepalive fsm */
+       if(ka_fsm_for_ts(il,bfd) && msg_type == IPAC_MSGT_PONG)
+               ipa_keepalive_fsm_pong_received(ka_fsm_for_ts(il,bfd));

        /* Handle IPA PING, PONG and ID_ACK messages. */
        ret = ipa_ccm_rcvmsg_base(msg, bfd);
@@ -152,6 +193,7 @@
                }
                /* the BSC creates the new sign links at this stage. */
                if (bfd->priv_nr == E1INP_SIGN_OML) {
+                       struct osmo_fsm_inst** f = &ka_fsm_for_ts(il,bfd);
                        sign_link =
                                line->ops->sign_link_up(&unit_data, line,
                                                        E1INP_SIGN_OML);
@@ -161,10 +203,22 @@
                                        "closing socket.\n");
                                goto err;
                        }
+
+                       if(*f)
+                               osmo_fsm_inst_free(*f);
+                       if(line->ipa_kap){
+                               *f = 
ipa_generic_conn_alloc_keepalive_fsm(tall_ipa_ctx, bfd, line->ipa_kap, 
"oml_bsc_to_bts");
+                               if(line->ipa_kap && f){
+                                       ipa_keepalive_fsm_set_timeout_cb(*f, 
ipa_bsc_keepalive_timeout_cb);
+                                       ipa_keepalive_fsm_set_send_cb(*f, 
ipa_bsc_keepalive_write_server_cb);
+                                       ipa_keepalive_fsm_start(*f);
+                               }
+                       }
                } else if (bfd->priv_nr == E1INP_SIGN_RSL) {
                        struct e1inp_ts *ts;
-                        struct osmo_fd *newbfd;
+                       struct osmo_fd *newbfd;
                        struct e1inp_line *new_line;
+                       struct osmo_fsm_inst** f;

                        sign_link =
                                line->ops->sign_link_up(&unit_data, line,
@@ -205,6 +259,19 @@
                        }
                        /* now we can release the dummy RSL line. */
                        e1inp_line_put(line);
+
+                       il = new_line->driver_data;
+                       f = &ka_fsm_for_ts(il,newbfd);
+                       if(*f)
+                               osmo_fsm_inst_free(*f);
+                       if(new_line->ipa_kap) {
+                               *f = 
ipa_generic_conn_alloc_keepalive_fsm(tall_ipa_ctx, newbfd, new_line->ipa_kap, 
"rsl_bsc_to_bts");
+                               if(f){
+                                       ipa_keepalive_fsm_set_timeout_cb(*f, 
ipa_bsc_keepalive_timeout_cb);
+                                       ipa_keepalive_fsm_set_send_cb(*f, 
ipa_bsc_keepalive_write_server_cb);
+                                       ipa_keepalive_fsm_start(*f);
+                               }
+                       }
                        return 1;
                }
                break;
@@ -231,6 +298,9 @@
        struct ipaccess_head *hh;
        struct msgb *msg = NULL;
        int ret, rc;
+       struct ipaccess_line *il = line->driver_data;
+       struct osmo_fsm_inst** f = &ka_fsm_for_ts(il,bfd);
+

        if (bfd->priv_nr == E1INP_SIGN_OML)
                e1i_ts = e1inp_line_ipa_oml_ts(line);
@@ -291,6 +361,9 @@
 err_msg:
        msgb_free(msg);
 err:
+       if(*f)
+               osmo_fsm_inst_free(*f);
+       *f = NULL;
        ipaccess_drop(bfd, line);
        return -EBADF;
 }
@@ -306,6 +379,14 @@
 {
        struct e1inp_ts *e1i_ts = sign_link->ts;
        struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
+       /* line might not exist if != bsc||bts */
+       struct e1inp_line *line = e1i_ts->line;
+       struct ipaccess_line *il = line ? line->driver_data : 0;
+
+       /* depending on caller the fsm might be dead */
+       if(il && ka_fsm_for_ts(il,bfd))
+               ipa_keepalive_fsm_stop(ka_fsm_for_ts(il,bfd));
+
        return e1inp_close_socket(e1i_ts, sign_link, bfd);
 }

@@ -324,6 +405,8 @@
        struct e1inp_sign_link *sign_link;
        struct msgb *msg;
        int ret;
+       struct ipaccess_line *il = line->driver_data;
+       struct osmo_fsm_inst** f = &ka_fsm_for_ts(il,bfd);

        if (bfd->priv_nr == E1INP_SIGN_OML)
                e1i_ts = e1inp_line_ipa_oml_ts(line);
@@ -372,6 +455,9 @@
        msgb_free(msg);
        return ret;
 err:
+       if(*f)
+               osmo_fsm_inst_free(*f);
+       *f = NULL;
        ipaccess_drop(bfd, line);
        msgb_free(msg);
        return ret;
@@ -677,11 +763,15 @@
 static void ipaccess_bts_updown_cb(struct ipa_client_conn *link, int up)
 {
        struct e1inp_line *line = link->line;
+       struct ipaccess_line *il = line->driver_data;
+       struct osmo_fsm_inst *f = ka_fsm_for_ts(il,link->ofd);

-        if (up) {
-                update_fd_settings(line, link->ofd->fd);
-                return;
-        }
+       if (up) {
+               update_fd_settings(line, link->ofd->fd);
+               if(f && line->ipa_kap)
+                       ipa_keepalive_fsm_start(f);
+               return;
+       }

        if (line->ops->sign_link_down)
                line->ops->sign_link_down(line);
@@ -695,11 +785,18 @@
        struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
        struct msgb *rmsg;
        int ret = 0;
+       /* line might not exist if != bsc||bts */
+       struct e1inp_line *line = link->line;
+       struct ipaccess_line *il = line ? line->driver_data : 0;

        /* special handling for IPA CCM. */
        if (hh->proto == IPAC_PROTO_IPACCESS) {
                uint8_t msg_type = *(msg->l2h);

+               /* peek the pong for our keepalive fsm */
+               if(il && ka_fsm_for_ts(il,link->ofd) && msg_type == 
IPAC_MSGT_PONG)
+                       
ipa_keepalive_fsm_pong_received(ka_fsm_for_ts(il,link->ofd));
+
                /* ping, pong and acknowledgment cases. */
                ret = ipa_ccm_rcvmsg_bts_base(msg, link->ofd);
                if (ret < 0)
@@ -823,9 +920,21 @@
        return -EBADF;
 }

-struct ipaccess_line {
-       int line_already_initialized;
-};
+static void ipa_bts_keepalive_write_client_cb(struct osmo_fsm_inst *fi, void 
*conn, struct msgb *msg){
+       struct ipa_client_conn *link = (struct ipa_client_conn *)conn;
+       int ret = 0;
+
+       ret = ipa_send(link->ofd->fd, msg->data, msg->len);
+       if (ret != msg->len) {
+               LOGP(DLINP, LOGL_ERROR, "cannot send message. Reason: %s\n", 
strerror(errno));
+       }
+       msgb_free(msg);
+}
+
+static int ipa_bts_keepalive_timeout_cb(struct osmo_fsm_inst *fi, void *conn){
+       ipaccess_bts_updown_cb(conn, false);
+       return 1;
+}

 static int ipaccess_line_update(struct e1inp_line *line)
 {
@@ -889,6 +998,7 @@
        }
        case E1INP_LINE_R_BTS: {
                struct ipa_client_conn *link;
+               struct osmo_fsm_inst** f = &il->ka_fsm[0];
 
                LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode, "
                     "OML connecting to %s:%u\n", line->ops->cfg.ipa.addr,
@@ -915,6 +1025,17 @@
                        ipa_client_conn_destroy(link);
                        return -EIO;
                }
+
+               if(*f)
+                       osmo_fsm_inst_free(*f);
+               if(line->ipa_kap){
+                       *f = ipa_client_conn_alloc_keepalive_fsm(link, 
line->ipa_kap, "oml_bts_to_bsc");
+                       if(*f){
+                               ipa_keepalive_fsm_set_timeout_cb(*f, 
ipa_bts_keepalive_timeout_cb);
+                               ipa_keepalive_fsm_set_send_cb(*f, 
ipa_bts_keepalive_write_client_cb);
+                       }
+               }
+
                ret = 0;
                break;
        }
@@ -924,7 +1045,6 @@
        return ret;
 }

-
 /* backwards compatibility */
 int e1inp_ipa_bts_rsl_connect(struct e1inp_line *line,
                              const char *rem_addr, uint16_t rem_port)
@@ -937,6 +1057,8 @@
                                uint8_t trx_nr)
 {
        struct ipa_client_conn *rsl_link;
+       struct ipaccess_line *il = line->driver_data;
+       struct osmo_fsm_inst** f = &il->ka_fsm[1+trx_nr];

        if (E1INP_SIGN_RSL+trx_nr-1 >= NUM_E1_TS) {
                LOGP(DLINP, LOGL_ERROR, "cannot create RSL BTS link: "
@@ -964,6 +1086,17 @@
                ipa_client_conn_destroy(rsl_link);
                return -EIO;
        }
+
+       if(*f)
+               osmo_fsm_inst_free(*f);
+       if(line->ipa_kap){
+               *f = ipa_client_conn_alloc_keepalive_fsm(rsl_link, 
line->ipa_kap, "rsl_bts_to_bsc");
+               if(*f){
+                       ipa_keepalive_fsm_set_timeout_cb(*f, 
ipa_bts_keepalive_timeout_cb);
+                       ipa_keepalive_fsm_set_send_cb(*f, 
ipa_bts_keepalive_write_client_cb);
+               }
+       }
+
        return 0;
 }


--
To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/14743
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Change-Id: I30e3bd601e55355aaf738ee2f2c44c1ec2c46c6a
Gerrit-Change-Number: 14743
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <[email protected]>
Gerrit-MessageType: newchange

Reply via email to