* getting lldp DCB_CMD_IEEE_GET after DCB_CMD_GCAP fails
@ 2013-10-15 16:18 Olaf Hering
2013-10-18 15:40 ` Olaf Hering
0 siblings, 1 reply; 2+ messages in thread
From: Olaf Hering @ 2013-10-15 16:18 UTC (permalink / raw)
To: netdev
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;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: getting lldp DCB_CMD_IEEE_GET after DCB_CMD_GCAP fails
2013-10-15 16:18 getting lldp DCB_CMD_IEEE_GET after DCB_CMD_GCAP fails Olaf Hering
@ 2013-10-18 15:40 ` Olaf Hering
0 siblings, 0 replies; 2+ messages in thread
From: Olaf Hering @ 2013-10-18 15:40 UTC (permalink / raw)
To: netdev
On Tue, Oct 15, Olaf Hering wrote:
> Is the code below supposed to work anyway? Thanks for any help.
For some reason libnl does require an ack handler. Without such handler,
if the data and the actual ack are sent back to the application with two
independent messages, the second recv will just be the ack. My example
did not take this into account. Now I changed it to something like this:
do {
nl_recvmsgs(handle, cb);
} while (ack == 0);
Now it happens to work.
Olaf
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-10-18 15:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-15 16:18 getting lldp DCB_CMD_IEEE_GET after DCB_CMD_GCAP fails Olaf Hering
2013-10-18 15:40 ` Olaf Hering
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).