netlink: add beginning of netlink LLME support
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
9bd59b4751
commit
472733d43d
|
@ -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 */
|
||||
|
|
|
@ -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)))
|
||||
|
|
217
src/netlink.c
217
src/netlink.c
|
@ -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:
|
||||
|
|
Reference in New Issue