dect
/
libdect
Archived
13
0
Fork 0

netlink: add beginning of netlink LLME support

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-03-10 14:17:50 +01:00
parent 9bd59b4751
commit 472733d43d
3 changed files with 218 additions and 32 deletions

View File

@ -5,6 +5,15 @@
#include <dect/libdect.h>
#include <list.h>
struct dect_fp_capabilities {
uint32_t fpc;
uint16_t hlc;
uint16_t efpc;
uint32_t ehlc;
uint16_t efpc2;
uint32_t ehlc2;
};
/**
* struct dect_handle - libdect handle
*
@ -14,25 +23,28 @@
* @index: cluster index
* @mode: cluster mode
* @pari: FP's PARI
* @fpc: FP capabilities
* @b_sap: B-SAP socket
* @s_sap: S-SAP listener socket
* @links: list of data links
* @mme_list: MM endpoint list
*/
struct dect_handle {
const struct dect_ops *ops;
struct nl_sock *nlsock;
struct dect_fd *nlfd;
const struct dect_ops *ops;
unsigned int index;
enum dect_cluster_modes mode;
struct dect_ari pari;
struct nl_sock *nlsock;
struct dect_fd *nlfd;
struct dect_fd *b_sap;
struct dect_fd *s_sap;
struct list_head links;
int index;
enum dect_cluster_modes mode;
struct dect_ari pari;
struct dect_fp_capabilities fpc;
struct list_head mme_list;
struct dect_fd *b_sap;
struct dect_fd *s_sap;
struct list_head links;
struct list_head mme_list;
};
#endif /* _LIBDECT_H */

View File

@ -16,6 +16,7 @@
#define __init __attribute__((constructor))
#define __exit __attribute__((destructor))
#define __must_check __attribute__((warn_unused_result))
#define __maybe_unused __attribute__((unused))
#define __noreturn __attribute__((__noreturn__))
#define __fmtstring(x, y) __attribute__((format(printf, x, y)))
#define __aligned(x) __attribute__((aligned(x)))

View File

@ -1,7 +1,7 @@
/*
* DECT Netlink Interface
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
* Copyright (c) 2009-2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -17,16 +17,61 @@
#include <netlink/object.h>
#include <netlink/msg.h>
#include <netlink/dect/cluster.h>
#include <netlink/dect/llme.h>
#include <netlink/dect/ari.h>
#include <libdect.h>
#include <netlink.h>
#include <utils.h>
#define nl_debug_entry(fmt, args...) \
dect_debug("\nnetlink: " fmt, ## args)
#define nl_debug(fmt, args...) \
dect_debug("netlink: " fmt, ## args)
struct dect_netlink_handler {
struct dect_handle *dh;
void (*rcv)(struct dect_handle *,
struct nl_object *);
};
static void __maybe_unused dect_netlink_obj_dump(struct nl_object *obj)
{
#ifdef DEBUG
char buf[2048];
struct nl_dump_params dp = {
.dp_type = NL_DUMP_LINE,
.dp_buf = buf,
.dp_buflen = sizeof(buf),
};
buf[0] = '\0';
nl_object_dump(obj, &dp);
dect_debug("%s", buf);
#endif
}
static void dect_netlink_obj_rcv(struct nl_object *obj, void *arg)
{
struct dect_netlink_handler *handler = arg;
handler->rcv(handler->dh, obj);
}
static int dect_netlink_msg_rcv(struct nl_msg *msg, void *arg)
{
if (nl_msg_parse(msg, dect_netlink_obj_rcv, arg) < 0)
nl_debug("message parsing failed type %u\n",
nlmsg_hdr(msg)->nlmsg_type);
return NL_OK;
}
static void dect_netlink_event(struct dect_handle *dh, struct dect_fd *fd,
uint32_t event)
{
nl_recvmsgs_default(dh->nlsock);
if (nl_recvmsgs_default(dh->nlsock) < 0)
nl_debug("nl_recvmsgs: %s\n", strerror(errno));
}
static void dect_netlink_set_callback(struct dect_handle *dh,
@ -36,6 +81,10 @@ static void dect_netlink_set_callback(struct dect_handle *dh,
nl_socket_modify_cb(dh->nlsock, NL_CB_VALID, NL_CB_CUSTOM, func, arg);
}
/*
* Cluster
*/
static void dect_netlink_parse_ari(struct dect_ari *ari, const struct nl_dect_ari *nlari)
{
ari->arc = nl_dect_ari_get_class(nlari);
@ -65,28 +114,150 @@ static void dect_netlink_parse_ari(struct dect_ari *ari, const struct nl_dect_ar
}
}
static void get_cluster_cb(struct nl_object *obj, void *arg)
static void dect_netlink_cluster_rcv(struct dect_handle *dh, struct nl_object *obj)
{
struct dect_handle *dh = arg;
struct nl_dect_cluster *cl = (struct nl_dect_cluster *)obj;
struct nl_dect_cluster *cl = nl_object_priv(obj);
dh->index = nl_dect_cluster_get_index(cl);
dh->mode = nl_dect_cluster_get_mode(cl);
dect_netlink_parse_ari(&dh->pari, nl_dect_cluster_get_pari(cl));
dect_debug("netlink: %s: mode %s ARI: class A: EMC: %.4x FPN: %.5x\n",
nl_dect_cluster_get_name(cl),
dh->mode == DECT_MODE_FP ? "FP" : "PP",
dh->pari.emc, dh->pari.fpn);
nl_debug("%s: mode %s ARI: class A: EMC: %.4x FPN: %.5x\n",
nl_dect_cluster_get_name(cl),
dh->mode == DECT_MODE_FP ? "FP" : "PP",
dh->pari.emc, dh->pari.fpn);
}
static int dect_netlink_get_cluster_cb(struct nl_msg *msg, void *arg)
static int dect_netlink_get_cluster(struct dect_handle *dh, const char *name)
{
return nl_msg_parse(msg, get_cluster_cb, arg);
struct dect_netlink_handler handler = {
.dh = dh,
.rcv = dect_netlink_cluster_rcv,
};
struct nl_dect_cluster *cl;
int err;
cl = nl_dect_cluster_alloc();
if (cl == NULL)
return -1;
nl_dect_cluster_set_name(cl, name);
dect_netlink_set_callback(dh, dect_netlink_msg_rcv, &handler);
err = nl_dect_cluster_query(dh->nlsock, cl, 0);
dect_netlink_set_callback(dh, NULL, NULL);
nl_dect_cluster_put(cl);
return err;
}
/*
* LLME
*/
static void dect_fp_capabilities_dump(struct dect_fp_capabilities *fpc)
{
char buf1[256], buf2[256], buf3[256];
nl_dect_llme_fpc2str(fpc->fpc, buf1, sizeof(buf1));
nl_dect_llme_efpc2str(fpc->efpc, buf2, sizeof(buf2));
nl_dect_llme_efpc22str(fpc->efpc2, buf3, sizeof(buf3));
nl_debug("FPC: %s%s%s%s%s\n",
buf1, buf1[0] && (buf2[0] || buf3[0]) ? "," : "",
buf2, buf2[0] && buf3[0] ? "," : "", buf3);
nl_dect_llme_hlc2str(fpc->hlc, buf1, sizeof(buf1));
nl_dect_llme_ehlc2str(fpc->ehlc, buf2, sizeof(buf2));
nl_dect_llme_ehlc22str(fpc->ehlc2, buf3, sizeof(buf3));
nl_debug("HLC: %s%s%s%s%s\n",
buf1, buf1[0] && (buf2[0] || buf3[0]) ? "," : "",
buf2, buf2[0] && buf3[0] ? "," : "", buf3);
}
static void dect_netlink_llme_mac_info_rcv(struct dect_handle *dh,
struct nl_dect_llme_msg *lmsg)
{
struct dect_fp_capabilities *fpc = &dh->fpc;
fpc->fpc = nl_dect_llme_mac_info_get_fpc(lmsg);
fpc->hlc = nl_dect_llme_mac_info_get_hlc(lmsg);
fpc->efpc = nl_dect_llme_mac_info_get_efpc(lmsg);
fpc->ehlc = nl_dect_llme_mac_info_get_ehlc(lmsg);
fpc->efpc2 = nl_dect_llme_mac_info_get_efpc2(lmsg);
fpc->ehlc2 = nl_dect_llme_mac_info_get_ehlc2(lmsg);
dect_fp_capabilities_dump(fpc);
}
static void dect_netlink_llme_rcv(struct dect_handle *dh, struct nl_object *obj)
{
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
enum dect_llme_msg_types type;
enum dect_llme_ops op;
type = nl_dect_llme_msg_get_type(lmsg);
op = nl_dect_llme_msg_get_op(lmsg);
#define LLME_MSG(type, op) (type << 16 | op)
switch (LLME_MSG(type, op)) {
case LLME_MSG(DECT_LLME_MAC_INFO, DECT_LLME_INDICATE):
return dect_netlink_llme_mac_info_rcv(dh, lmsg);
default:
nl_debug("unknown LLME message: type: %u op: %u\n", type, op);
dect_netlink_obj_dump(obj);
}
}
static int dect_netlink_mac_info_req(struct dect_handle *dh)
{
struct dect_netlink_handler handler = {
.dh = dh,
.rcv = dect_netlink_llme_rcv,
};
struct nl_dect_llme_msg *lmsg;
int err;
lmsg = nl_dect_llme_msg_alloc();
if (lmsg == NULL)
return -1;
nl_dect_llme_msg_set_type(lmsg, DECT_LLME_MAC_INFO);
nl_dect_llme_msg_set_op(lmsg, DECT_LLME_REQUEST);
nl_dect_llme_msg_set_index(lmsg, dh->index);
dect_netlink_set_callback(dh, dect_netlink_msg_rcv, &handler);
err = nl_dect_llme_request(dh->nlsock, lmsg);
dect_netlink_set_callback(dh, NULL, NULL);
nl_dect_llme_msg_put(lmsg);
return err;
}
static int dect_netlink_event_rcv(struct nl_msg *msg, void *arg)
{
struct sockaddr_nl *addr = nlmsg_get_src(msg);
struct dectmsg *dm = nlmsg_data(nlmsg_hdr(msg));
struct dect_handle *dh = arg;
struct dect_netlink_handler handler = { .dh = dh };
unsigned int group = ffs(addr->nl_groups);
if (dm->dm_index != dh->index)
return NL_OK;
nl_debug_entry("message group: %u\n", group);
switch (group) {
case DECTNLGRP_CLUSTER:
handler.rcv = dect_netlink_cluster_rcv;
break;
case DECTNLGRP_LLME:
handler.rcv = dect_netlink_llme_rcv;
break;
default:
nl_debug("unknown message source\n");
return NL_OK;
}
return dect_netlink_msg_rcv(msg, &handler);
}
int dect_netlink_init(struct dect_handle *dh)
{
struct nl_dect_cluster *cl;
int err = 0;
dh->nlsock = nl_socket_alloc();
@ -110,20 +281,22 @@ int dect_netlink_init(struct dect_handle *dh)
if (dect_register_fd(dh, dh->nlfd, DECT_FD_READ))
goto err3;
cl = nl_dect_cluster_alloc();
if (cl == NULL)
goto err4;
nl_dect_cluster_set_name(cl, "cluster0");
dect_netlink_set_callback(dh, dect_netlink_get_cluster_cb, dh);
err = nl_dect_cluster_query(dh->nlsock, cl, 0);
dect_netlink_set_callback(dh, NULL, NULL);
nl_dect_cluster_put(cl);
err = dect_netlink_get_cluster(dh, "cluster0");
if (err < 0)
goto err4;
if (dh->mode == DECT_MODE_PP) {
err = dect_netlink_mac_info_req(dh);
if (err < 0)
goto err4;
}
dect_netlink_set_callback(dh, dect_netlink_event_rcv, dh);
nl_socket_disable_seq_check(dh->nlsock);
nl_socket_add_membership(dh->nlsock, DECTNLGRP_CLUSTER);
nl_socket_add_membership(dh->nlsock, DECTNLGRP_LLME);
return 0;
err4:
dect_unregister_fd(dh, dh->nlfd);
err3: