From 19d5a4fead0a0b9b9aa30b7e1476edd9808f0613 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 29 Jun 2018 07:33:39 -0400 Subject: [PATCH 1/2] zebra: Listen to error codes from netlink_socket When creating a netlink_socket, listen to error codes and abandon ship if it crashes and burns. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 062fa9299c..73f64de7f3 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -942,12 +942,20 @@ void kernel_init(struct zebra_ns *zns) snprintf(zns->netlink.name, sizeof(zns->netlink.name), "netlink-listen (NS %u)", zns->ns_id); zns->netlink.sock = -1; - netlink_socket(&zns->netlink, groups, zns->ns_id); + if (netlink_socket(&zns->netlink, groups, zns->ns_id) < 0) { + zlog_err("Failure to create %s socket", + zns->netlink.name); + exit(-1); + } snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name), "netlink-cmd (NS %u)", zns->ns_id); zns->netlink_cmd.sock = -1; - netlink_socket(&zns->netlink_cmd, 0, zns->ns_id); + if (netlink_socket(&zns->netlink_cmd, 0, zns->ns_id) < 0) { + zlog_err("Failure to create %s socket", + zns->netlink_cmd.name); + exit(-1); + } /* * SOL_NETLINK is not available on all platforms yet @@ -969,23 +977,20 @@ void kernel_init(struct zebra_ns *zns) #endif /* Register kernel socket. */ - if (zns->netlink.sock > 0) { - /* Only want non-blocking on the netlink event socket */ - if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err("Can't set %s socket flags: %s", - zns->netlink.name, safe_strerror(errno)); + if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket flags: %s", + zns->netlink.name, safe_strerror(errno)); - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - netlink_recvbuf(&zns->netlink, nl_rcvbufsize); + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf(&zns->netlink, nl_rcvbufsize); - netlink_install_filter(zns->netlink.sock, - zns->netlink_cmd.snl.nl_pid); - zns->t_netlink = NULL; + netlink_install_filter(zns->netlink.sock, + zns->netlink_cmd.snl.nl_pid); + zns->t_netlink = NULL; - thread_add_read(zebrad.master, kernel_read, zns, - zns->netlink.sock, &zns->t_netlink); - } + thread_add_read(zebrad.master, kernel_read, zns, + zns->netlink.sock, &zns->t_netlink); rt_netlink_init(); } From 8c85e8ea92808ecbf8d301b00e991784830024a7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 29 Jun 2018 09:49:08 -0400 Subject: [PATCH 2/2] zebra: Remove need for ACK for netlink messages Kernel requests via netlink are synchronous. Therefore we do not need to specify a need for a ACK and we can make the netlink_cmd NONBLOCKING 1) If the netlink message is going to cause an error we will still get one. Since results from the kernel are synchronous we will get the error message on the netlink_cmd socket and handle it 2) If the netlink message is going to send more than one packet we will still get them all. Since the results from the kernel are synchronous we will receive all data. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 73f64de7f3..8703b01319 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -829,9 +829,6 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), n->nlmsg_seq = ++nl->seq; n->nlmsg_pid = nl->snl.nl_pid; - /* Request an acknowledgement by setting NLM_F_ACK */ - n->nlmsg_flags |= NLM_F_ACK; - if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", @@ -978,8 +975,12 @@ void kernel_init(struct zebra_ns *zns) /* Register kernel socket. */ if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err("Can't set %s socket flags: %s", - zns->netlink.name, safe_strerror(errno)); + zlog_err("Can't set %s socket error: %s(%d)", + zns->netlink.name, safe_strerror(errno), errno); + + if (fcntl(zns->netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket error: %s(%d)", + zns->netlink_cmd.name, safe_strerror(errno), errno); /* Set receive buffer size if it's set from command line */ if (nl_rcvbufsize)