summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/log.c3
-rw-r--r--lib/thread.c77
-rw-r--r--lib/yang_wrappers.c23
-rw-r--r--lib/yang_wrappers.h2
-rw-r--r--lib/zclient.c20
-rw-r--r--lib/zclient.h5
6 files changed, 92 insertions, 38 deletions
diff --git a/lib/log.c b/lib/log.c
index 202d6d858f..4054185019 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -451,7 +451,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES),
DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE),
DESC_ENTRY(ZEBRA_OPAQUE_REGISTER),
- DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER)};
+ DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER),
+ DESC_ENTRY(ZEBRA_NEIGH_DISCOVER)};
#undef DESC_ENTRY
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
diff --git a/lib/thread.c b/lib/thread.c
index 1df4eee25c..19e4827283 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -726,17 +726,16 @@ static void thread_free(struct thread_master *master, struct thread *thread)
static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
nfds_t count, const struct timeval *timer_wait)
{
- /* If timer_wait is null here, that means poll() should block
- * indefinitely,
- * unless the thread_master has overridden it by setting
+ /*
+ * If timer_wait is null here, that means poll() should block
+ * indefinitely, unless the thread_master has overridden it by setting
* ->selectpoll_timeout.
+ *
* If the value is positive, it specifies the maximum number of
- * milliseconds
- * to wait. If the timeout is -1, it specifies that we should never wait
- * and
- * always return immediately even if no event is detected. If the value
- * is
- * zero, the behavior is default. */
+ * milliseconds to wait. If the timeout is -1, it specifies that
+ * we should never wait and always return immediately even if no
+ * event is detected. If the value is zero, the behavior is default.
+ */
int timeout = -1;
/* number of file descriptors with events */
@@ -860,7 +859,7 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
frr_with_mutex(&m->mtx) {
if (t_ptr && *t_ptr)
- // thread is already scheduled; don't reschedule
+ /* thread is already scheduled; don't reschedule */
return NULL;
thread = thread_get(m, type, func, arg, debugargpass);
@@ -940,7 +939,7 @@ struct thread *funcname_thread_add_event(struct thread_master *m,
frr_with_mutex(&m->mtx) {
if (t_ptr && *t_ptr)
- // thread is already scheduled; don't reschedule
+ /* thread is already scheduled; don't reschedule */
break;
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
@@ -1047,11 +1046,12 @@ static void do_thread_cancel(struct thread_master *master)
struct cancel_req *cr;
struct listnode *ln;
for (ALL_LIST_ELEMENTS_RO(master->cancel_req, ln, cr)) {
- /* If this is an event object cancellation, linear search
- * through event
- * list deleting any events which have the specified argument.
- * We also
- * need to check every thread in the ready queue. */
+ /*
+ * If this is an event object cancellation, linear search
+ * through event list deleting any events which have the
+ * specified argument. We also need to check every thread
+ * in the ready queue.
+ */
if (cr->eventobj) {
struct thread *t;
@@ -1075,11 +1075,12 @@ static void do_thread_cancel(struct thread_master *master)
continue;
}
- /* The pointer varies depending on whether the cancellation
- * request was
- * made asynchronously or not. If it was, we need to check
- * whether the
- * thread even exists anymore before cancelling it. */
+ /*
+ * The pointer varies depending on whether the cancellation
+ * request was made asynchronously or not. If it was, we
+ * need to check whether the thread even exists anymore
+ * before cancelling it.
+ */
thread = (cr->thread) ? cr->thread : *cr->threadref;
if (!thread)
@@ -1304,18 +1305,21 @@ static void thread_process_io(struct thread_master *m, unsigned int num)
ready++;
- /* Unless someone has called thread_cancel from another pthread,
- * the only
- * thing that could have changed in m->handler.pfds while we
- * were
- * asleep is the .events field in a given pollfd. Barring
- * thread_cancel()
- * that value should be a superset of the values we have in our
- * copy, so
- * there's no need to update it. Similarily, barring deletion,
- * the fd
- * should still be a valid index into the master's pfds. */
- if (pfds[i].revents & (POLLIN | POLLHUP)) {
+ /*
+ * Unless someone has called thread_cancel from another
+ * pthread, the only thing that could have changed in
+ * m->handler.pfds while we were asleep is the .events
+ * field in a given pollfd. Barring thread_cancel() that
+ * value should be a superset of the values we have in our
+ * copy, so there's no need to update it. Similarily,
+ * barring deletion, the fd should still be a valid index
+ * into the master's pfds.
+ *
+ * We are including POLLERR here to do a READ event
+ * this is because the read should fail and the
+ * read function should handle it appropriately
+ */
+ if (pfds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
thread_process_io_helper(m, m->read[pfds[i].fd], POLLIN,
pfds[i].revents, i);
}
@@ -1427,11 +1431,10 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
*
* - If there are events pending, set the poll() timeout to zero
* - If there are no events pending, but there are timers
- * pending, set the
- * timeout to the smallest remaining time on any timer
+ * pending, set the timeout to the smallest remaining time on
+ * any timer.
* - If there are neither timers nor events pending, but there
- * are file
- * descriptors pending, block indefinitely in poll()
+ * are file descriptors pending, block indefinitely in poll()
* - If nothing is pending, it's time for the application to die
*
* In every case except the last, we need to hit poll() at least
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index 4f743096ee..4c658c1bfb 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -792,6 +792,29 @@ struct yang_data *yang_data_new_empty(const char *xpath)
return yang_data_new(xpath, NULL);
}
+bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt,
+ ...)
+{
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+ const struct lyd_node_leaf_list *dleaf;
+
+ assert(dnode);
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ dnode = yang_dnode_get(dnode, xpath);
+ if (dnode) {
+ dleaf = (const struct lyd_node_leaf_list *)dnode;
+ if (dleaf->value_type == LY_TYPE_EMPTY)
+ return true;
+ }
+
+ return false;
+}
+
/*
* Derived type: IP prefix.
*/
diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h
index 335ff319d5..d781dfb1e4 100644
--- a/lib/yang_wrappers.h
+++ b/lib/yang_wrappers.h
@@ -120,6 +120,8 @@ extern void yang_get_default_string_buf(char *buf, size_t size,
/* empty */
extern struct yang_data *yang_data_new_empty(const char *xpath);
+extern bool yang_dnode_get_empty(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...);
/* ip prefix */
extern void yang_str2prefix(const char *value, union prefixptr prefix);
diff --git a/lib/zclient.c b/lib/zclient.c
index 6449fe15b9..808aa18bbe 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -3953,3 +3953,23 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
stream_failure:
return 0;
}
+
+int zclient_send_neigh_discovery_req(struct zclient *zclient,
+ const struct interface *ifp,
+ const struct prefix *p)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
+ stream_putl(s, ifp->ifindex);
+
+ stream_putc(s, p->family);
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->u.prefix, prefix_blen(p));
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+ return zclient_send_message(zclient);
+}
diff --git a/lib/zclient.h b/lib/zclient.h
index bcdae85823..dab384d5ec 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -214,6 +214,7 @@ typedef enum {
ZEBRA_OPAQUE_MESSAGE,
ZEBRA_OPAQUE_REGISTER,
ZEBRA_OPAQUE_UNREGISTER,
+ ZEBRA_NEIGH_DISCOVER,
} zebra_message_types_t;
enum zebra_error_types {
@@ -956,6 +957,10 @@ enum zapi_opaque_registry {
*/
extern int zclient_send_hello(struct zclient *client);
+extern int zclient_send_neigh_discovery_req(struct zclient *zclient,
+ const struct interface *ifp,
+ const struct prefix *p);
+
#ifdef __cplusplus
}
#endif