[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20131015161838.GA10478@aepfle.de>
Date: Tue, 15 Oct 2013 18:18:39 +0200
From: Olaf Hering <olaf@...fle.de>
To: netdev@...r.kernel.org
Subject: getting lldp DCB_CMD_IEEE_GET after DCB_CMD_GCAP fails
If this list is the wrong place, please point me to the right direction.
In the example code below the part which grabs DCB_CMD_IEEE_GET fails,
unless the "hack" part is executed. What I see inside the kernel is that
__netlink_dump_start gets to the err=-EBUSY case because nlk->cb is
still set. The nl_ack_handler is executed, an "empty" error is returned.
I have compared my code with open-lldp-0.9.46/test/nltest.c and did not
spot the difference.
Is the code below supposed to work anyway? Thanks for any help.
Olaf
/* cc -lnl lldptest.c -o lldptest */
#include <stdio.h>
#include <netlink/msg.h>
#include <linux/dcbnl.h>
static int nl_dump_valid(struct nl_msg *msg, void *p)
{
struct nlmsghdr *nlh = p;
nlh = nlmsg_hdr(msg);
printf("%s: %x\n", __func__, nlh->nlmsg_len);
return NL_OK;
}
static int nl_ack_handler(struct nl_msg *msg, void *arg)
{
arg = msg;
printf("%s: %p\n", __func__, arg);
return NL_STOP;
}
static int nl_error_handler(struct sockaddr_nl *sender, struct nlmsgerr *err, void *arg)
{
char *s = arg;
printf("%s: %p %s %x\n", __func__, sender, s, err->error);
return NL_STOP;
}
int main(int argc, char *argv[])
{
struct nl_handle *nl_handle;
struct nl_cb *nl_cb, *tmp_cb;
struct nl_msg *msg;
struct nlattr *nla;
struct dcbmsg dcb = {.dcb_family = AF_UNSPEC, };
char *ifname;
int hack;
int protocol = 0;
int ret = 1;
if (argc < 2) {
printf("Usage: %s <ifname> [hack]\n", argv[0]);
goto out;
}
ifname = argv[1];
hack = !!argv[2];
nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!nl_cb) {
perror("nl_cb_alloc");
goto out;
}
nl_handle = nl_handle_alloc_cb(nl_cb);
if (nl_connect(nl_handle, protocol) < 0) {
perror("nl_connect");
goto out;
}
tmp_cb = nl_cb_clone(nl_cb);
dcb.cmd = DCB_CMD_GCAP;
nl_cb_err(tmp_cb, NL_CB_CUSTOM, nl_error_handler, "DCB_CMD_GCAP");
nl_cb_set(tmp_cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, NULL);
nl_cb_set(tmp_cb, NL_CB_VALID, NL_CB_CUSTOM, nl_dump_valid, NULL);
msg = nlmsg_alloc_simple(RTM_GETDCB, NLM_F_REQUEST);
if (!msg) {
perror("nlmsg_alloc_simple");
goto out;
}
if (nlmsg_append(msg, &dcb, sizeof(dcb), NLMSG_ALIGNTO) < 0) {
perror("nlmsg_append");
goto out;
}
NLA_PUT_STRING(msg, DCB_ATTR_IFNAME, ifname);
nla = nla_nest_start(msg, DCB_ATTR_CAP);
NLA_PUT_FLAG(msg, DCB_CAP_ATTR_ALL);
nla_nest_end(msg, nla);
if (nl_send_auto_complete(nl_handle, msg) < 0) {
perror("nl_send_auto_complete");
goto out;
}
if ((nl_recvmsgs(nl_handle, tmp_cb)) < 0) {
perror("nl_recvmsgs");
goto out;
}
nl_cb_put(tmp_cb);
nlmsg_free(msg);
if (hack) {
nl_close(nl_handle);
nl_handle = nl_handle_alloc_cb(nl_cb);
if (nl_connect(nl_handle, protocol) < 0) {
perror("nl_connect");
goto out;
}
}
tmp_cb = nl_cb_clone(nl_cb);
dcb.cmd = DCB_CMD_IEEE_GET;
nl_cb_err(tmp_cb, NL_CB_CUSTOM, nl_error_handler, "DCB_CMD_IEEE_GET");
nl_cb_set(tmp_cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, NULL);
nl_cb_set(tmp_cb, NL_CB_VALID, NL_CB_CUSTOM, nl_dump_valid, NULL);
msg = nlmsg_alloc_simple(RTM_GETDCB, NLM_F_REQUEST);
if (!msg) {
perror("nlmsg_alloc_simple");
goto out;
}
if (nlmsg_append(msg, &dcb, sizeof(dcb), NLMSG_ALIGNTO) < 0) {
perror("nlmsg_append");
goto out;
}
NLA_PUT_STRING(msg, DCB_ATTR_IFNAME, ifname);
if (nl_send_auto_complete(nl_handle, msg) < 0) {
perror("nl_send_auto_complete");
goto out;
}
if ((nl_recvmsgs(nl_handle, tmp_cb)) < 0) {
perror("nl_recvmsgs");
goto out;
}
nl_cb_put(tmp_cb);
nlmsg_free(msg);
ret = 0;
nla_put_failure:
out:
return ret;
}
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists