summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/p1905_managerd/src/alme.c
diff options
context:
space:
mode:
authorsamuel.chou2013-10-03 10:48:50 +0800
committersamuel.chou2013-10-11 09:33:12 +0800
commitef5c0c79316f864a38feee254c14a07fe409734c (patch)
treec8ba5986fc43ea5c2286d595edca23bef8e37464 /cleopatre/devkit/p1905_managerd/src/alme.c
parentb413722410e6da5d2600688248e9a9bca91b352c (diff)
cleo/{linux/net/bridge,devkit/p1905}: add ieee1905.1 feature, closes #4220
Diffstat (limited to 'cleopatre/devkit/p1905_managerd/src/alme.c')
-rw-r--r--cleopatre/devkit/p1905_managerd/src/alme.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/cleopatre/devkit/p1905_managerd/src/alme.c b/cleopatre/devkit/p1905_managerd/src/alme.c
new file mode 100644
index 0000000000..1c446c1fa4
--- /dev/null
+++ b/cleopatre/devkit/p1905_managerd/src/alme.c
@@ -0,0 +1,367 @@
+/*
+ * cleopatre/application/p1905_managerd/src/alme.c
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+
+#include "p1905_managerd.h"
+#include "cmdu_tlv.h"
+#include "cmdu_message.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/sem.h>
+
+//#define ALME_DEBUG
+#ifdef ALME_DEBUG
+#define debug(...) printf(__VA_ARGS__)
+#define debug_syslog(...) printf(__VA_ARGS__)
+#else
+#define debug(...)
+#define debug_syslog(format, ...) syslog(LOG_WARNING, format, ##__VA_ARGS__)
+#endif
+
+typedef union semun
+{
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+}semun_t;
+
+static void parse_alme_get_metric_req(struct p1905_managerd_ctx *ctx, ALME_MSG *msg)
+{
+ ALME_GET_METRIC_REQ *req;
+#ifdef SUPPORT_WIFI
+ unsigned char sta_itf[6];
+#endif
+ req = (ALME_GET_METRIC_REQ *)msg->body;
+ //memcpy(ctx->link_metric_query_para.target, req->mac_addr, 6);
+ memcpy(ctx->link_metric_query_para.target, ctx->p1905_al_mac_addr, 6);
+
+ /*ALME does not define which type we should use, so I profile both RX/TX*/
+ ctx->link_metric_query_para.type = BOTH_TX_AND_RX_METRICS;
+
+ ctx->mid++;//message id increment
+ /*record message id, need to compare with the mid value from link metric response*/
+ ctx->link_metric_query_mid = ctx->mid;
+ /*query the link metrics of neighbor, send link metric query*/
+
+#ifdef SUPPORT_WIFI
+ /* if a AP want to send unicast cmdu to STA, it needs to use interface mac
+ * instead of AL mac address
+ */
+ if(is_neighbor_wifi_sta(ctx, sta_itf, req->mac_addr))
+ {
+ debug_syslog("3. STA neighbor: %.2x %.2x %.2x %.2x %.2x %.2x\n",
+ sta_itf[0], sta_itf[1], sta_itf[2], sta_itf[3], sta_itf[4], sta_itf[5]);
+ insert_cmdu_txq(sta_itf, ctx->p1905_al_mac_addr,
+ e_link_metric_response, ctx->mid);
+ }
+ else
+#endif
+ insert_cmdu_txq(req->mac_addr, ctx->p1905_al_mac_addr,\
+ e_link_metric_query, ctx->mid);
+
+ /*set alme state to alme_wait_4_link_metrics_rsp*/
+ ctx->alme_state = alme_wait_4_link_metrics_rsp;
+}
+
+int send_alme_get_metric_rsp(int fd, ALME_MSG *msg, ALME_REASON_CODE code)
+{
+ int len;
+
+ ALME_GET_METRIC_RSP *rsp;
+
+ msg->header.type = alme_get_metric_rsp;
+ msg->header.length = sizeof(ALME_GET_METRIC_RSP);
+
+ rsp = (ALME_GET_METRIC_RSP *)msg->body;
+ rsp->reason_code = code;
+
+ len = send(fd, msg, sizeof(ALME_MSG), 0);
+ if(len < 0)
+ {
+ debug_syslog("send ALME_GET_METRIC_RSP error(%s) reason %d\n",strerror(errno), code);
+ }
+ return len;
+}
+
+int wait_4_link_metric_rsp_timeout(int fd)
+{
+ ALME_MSG msg;
+ int len;
+
+ len = send_alme_get_metric_rsp(fd, &msg, alme_failure);
+ return len;
+}
+
+int send_alme_get_intf_list_rsp(struct p1905_managerd_ctx *ctx)
+{
+ int len, i;
+ ALME_MSG msg;
+ ALME_GET_INTF_LIST_RSP *rsp;
+ unsigned intf_num = 0;
+ struct p1905_neighbor_info *dev_info;
+
+
+ msg.header.type = alme_get_intf_list_rsp;
+ msg.header.length = sizeof(ALME_GET_INTF_LIST_RSP);
+
+ rsp = (ALME_GET_INTF_LIST_RSP *)msg.body;
+ rsp->intfnum = 0;
+
+ intf_num = ITF_NUM;
+
+ if(ITF_NUM > MAX_1905_LINK_NUM)
+ {
+ debug_syslog("ALME_GET_INTF_LIST_RSP too mush interface, %d\n", ITF_NUM);
+ intf_num = MAX_1905_LINK_NUM;
+ }
+
+ for(i=0;i<intf_num;i++)
+ {
+ memcpy(rsp->intflist[i].mac_addr, ctx->itf[i].mac_addr, 6);
+ rsp->intflist[i].intf_type = ctx->itf[i].media_type;
+ if(!LIST_EMPTY(&(ctx->p1905_neighbor_dev[i].p1905nbr_head)))
+ {
+ LIST_FOREACH(dev_info, &(ctx->p1905_neighbor_dev[i].p1905nbr_head),
+ p1905nbr_entry)
+ {
+ if(dev_info->ieee802_1_bridge == 1)
+ {
+ rsp->intflist[i].ieee802_1_bridge = 1;
+ break;
+ }
+ }
+ }
+ else
+ rsp->intflist[i].ieee802_1_bridge = 0;
+
+ rsp->intfnum++;
+ }
+
+ len = send(ctx->almefd, &msg, sizeof(ALME_MSG), 0);
+ if(len < 0)
+ {
+ debug_syslog("send ALME_GET_INTF_LIST_RSP error(%s)\n",strerror(errno));
+ }
+ return len;
+}
+
+int send_alme_get_1905_neighbor_rsp(struct p1905_managerd_ctx *ctx)
+{
+ int len;
+ ALME_MSG msg;
+ ALME_GET_1905_NEIGHBOR_RSP *rsp;
+ struct topology_discovery_db *tpg_db;
+ int i = 0;
+
+ msg.header.type = alme_get_1905_neighbor_rsp;
+ msg.header.length = sizeof(ALME_GET_1905_NEIGHBOR_RSP);
+
+ rsp = (ALME_GET_1905_NEIGHBOR_RSP *)msg.body;
+ rsp->neighbornum = 0;
+
+ /*query the topology discovery database to get 1905.1 neighbor*/
+ if(!LIST_EMPTY(&(ctx->topology_entry.tpddb_head)))
+ {
+ i = 0;
+ LIST_FOREACH(tpg_db, &(ctx->topology_entry.tpddb_head), tpddb_entry)
+ {
+ if(rsp->neighbornum == MAX_1905_NEIGHBOR_NUM)
+ break;
+
+ memcpy(&(rsp->neighborlist[i*6]), tpg_db->al_mac, 6);
+ rsp->neighbornum += 1;
+ i++;
+ }
+ }
+
+ len = send(ctx->almefd, &msg, sizeof(ALME_MSG), 0);
+ if(len < 0)
+ {
+ debug_syslog("send ALME_GET_1905_NEIGHBOR_RSP error(%s)\n",strerror(errno));
+ }
+ return len;
+}
+
+int ALME_init(struct p1905_managerd_ctx *ctx)
+{
+ struct sockaddr_un sock_addr;
+ int status = 0;
+
+ ctx->sock_alme = socket(AF_UNIX, SOCK_STREAM , 0);
+ if(ctx->sock_alme < 0)
+ {
+ debug_syslog("open ALME socket error\n");
+ return -1;
+ }
+
+ memset(&sock_addr, 0, sizeof(sock_addr));
+ sock_addr.sun_family = AF_UNIX;
+ strcpy(sock_addr.sun_path, "/tmp/alme_server");
+ status = bind(ctx->sock_alme, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
+ if(status < 0)
+ {
+ close(ctx->sock_alme);
+ debug_syslog("bind ALME fail(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if(listen(ctx->sock_alme, 1) < 0)
+ {
+ close(ctx->sock_alme);
+ debug_syslog("listen ALME fail(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ ctx->alme_state = alme_none;
+ ctx->almefd = -1;
+ ctx->alme_wait_4_link_metrics_cnt = 0;
+
+ return 0;
+}
+
+int ALME_sync_init(struct p1905_managerd_ctx *ctx)
+{
+ semun_t arg;
+ key_t key;
+
+ key = ftok("/tmp/alme_server",'a');
+ if(key == -1)
+ {
+ debug_syslog("create key for semaphore fail(%s)\n",strerror(errno));
+ close(ctx->sock_alme);
+ return -1;
+ }
+
+ /*create synchroniztion mechanism for libalme use*/
+ ctx->semid = semget(key, 1, 0666|IPC_CREAT);
+ if(ctx->semid < 0)
+ {
+ debug_syslog("create semaphore fail(%s)\n",strerror(errno));
+ close(ctx->sock_alme);
+ return -1;
+ }
+
+ arg.val = 1;
+ if (semctl(ctx->semid, 0, SETVAL, arg) == -1)
+ {
+ debug_syslog("init semaphore fail(%s)\n",strerror(errno));
+ close(ctx->sock_alme);
+
+ if(semctl(ctx->semid, 0, IPC_RMID, arg) == -1)
+ {
+ debug_syslog("de-allocate semaphore fail(%s)\n",strerror(errno));
+ return -1;
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+int ALME_uninit(struct p1905_managerd_ctx *ctx)
+{
+ close(ctx->sock_alme);
+
+ if(ctx->almefd > 0)
+ {
+ close(ctx->almefd);
+ ctx->almefd = -1;
+ }
+}
+
+int ALME_sync_uninit(struct p1905_managerd_ctx *ctx)
+{
+ semun_t arg;
+
+ if(semctl(ctx->semid, 0, IPC_RMID, arg) == -1)
+ {
+ debug_syslog("de-allocate semaphore fail(%s)\n",strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int alme_receive(struct p1905_managerd_ctx *ctx, unsigned char *buf, int len)
+{
+ struct sockaddr_un from;
+ int lenfrom = sizeof(from);
+
+ ctx->almefd = accept(ctx->sock_alme, (struct sockaddr *)&from, &lenfrom);
+ if(ctx->almefd < 0)
+ {
+ debug_syslog("accept alme fail\n");
+ return -1;
+ }
+
+ len = recv(ctx->almefd, buf, len, 0);
+ if(0 > len)
+ {
+ debug_syslog("recv alme fail\n");
+
+ if(ctx->almefd > 0)
+ {
+ close(ctx->almefd);
+ ctx->almefd = -1;
+ }
+ return -1;
+ }
+
+ /* we don't close ctx->almefd here because we may need this file descriptor
+ * to feedback alme message to HLE
+ */
+ //close(ctx->almefd);
+ return len;
+}
+
+int alme_process(struct p1905_managerd_ctx *ctx, unsigned char *buf, int len)
+{
+ ALME_MSG *msg;
+
+ msg = (ALME_MSG *)buf;
+
+ switch(msg->header.type)
+ {
+ case alme_get_metric_req:
+ parse_alme_get_metric_req(ctx, msg);
+ break;
+ case alme_get_intf_list_req:
+ send_alme_get_intf_list_rsp(ctx);
+ break;
+
+ /*below is MStar private*/
+ case alme_get_1905_neighbor_req:
+ send_alme_get_1905_neighbor_rsp(ctx);
+ break;
+ default:
+ break;
+ }
+
+
+ /* for some alme message, we can free the server and client connection.
+ * for alme_get_metric_req, we need to wait for receiving the link metrics response and then free connection.
+ * for .........
+ */
+ if(msg->header.type != alme_get_metric_req)
+ {
+ if(ctx->almefd > 0)
+ {
+ close(ctx->almefd);
+ ctx->almefd = -1;
+ }
+ }
+
+ return 0;
+}
+
+