diff options
Diffstat (limited to 'zebra/zebra_fpm.c')
| -rw-r--r-- | zebra/zebra_fpm.c | 139 |
1 files changed, 118 insertions, 21 deletions
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 34f0068514..5a68bcbfac 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -142,6 +142,15 @@ typedef enum { } zfpm_state_t; /* + * Message format to be used to communicate with the FPM. + */ +typedef enum +{ + ZFPM_MSG_FORMAT_NONE, + ZFPM_MSG_FORMAT_NETLINK, + ZFPM_MSG_FORMAT_PROTOBUF, +} zfpm_msg_format_e; +/* * Globals. */ typedef struct zfpm_glob_t_ @@ -152,6 +161,11 @@ typedef struct zfpm_glob_t_ */ int enabled; + /* + * Message format to be used to communicate with the fpm. + */ + zfpm_msg_format_e message_format; + struct thread_master *master; zfpm_state_t state; @@ -866,19 +880,40 @@ zfpm_writes_pending (void) */ static inline int zfpm_encode_route (rib_dest_t *dest, struct rib *rib, char *in_buf, - size_t in_buf_len) + size_t in_buf_len, fpm_msg_type_e *msg_type) { -#ifndef HAVE_NETLINK - return 0; -#else - + size_t len; int cmd; + len = 0; - cmd = rib ? RTM_NEWROUTE : RTM_DELROUTE; + *msg_type = FPM_MSG_TYPE_NONE; - return zfpm_netlink_encode_route (cmd, dest, rib, in_buf, in_buf_len); + switch (zfpm_g->message_format) { + case ZFPM_MSG_FORMAT_PROTOBUF: +#ifdef HAVE_PROTOBUF + len = zfpm_protobuf_encode_route (dest, rib, (uint8_t *) in_buf, + in_buf_len); + *msg_type = FPM_MSG_TYPE_PROTOBUF; +#endif + break; + + case ZFPM_MSG_FORMAT_NETLINK: +#ifdef HAVE_NETLINK + *msg_type = FPM_MSG_TYPE_NETLINK; + cmd = rib ? RTM_NEWROUTE : RTM_DELROUTE; + len = zfpm_netlink_encode_route (cmd, dest, rib, in_buf, in_buf_len); + assert(fpm_msg_align(len) == len); + *msg_type = FPM_MSG_TYPE_NETLINK; #endif /* HAVE_NETLINK */ + break; + + default: + break; + } + + return len; + } /* @@ -886,7 +921,7 @@ zfpm_encode_route (rib_dest_t *dest, struct rib *rib, char *in_buf, * * Returns the rib that is to be sent to the FPM for a given dest. */ -static struct rib * +struct rib * zfpm_route_for_update (rib_dest_t *dest) { struct rib *rib; @@ -922,6 +957,7 @@ zfpm_build_updates (void) fpm_msg_hdr_t *hdr; struct rib *rib; int is_add, write_msg; + fpm_msg_type_e msg_type; s = zfpm_g->obuf; @@ -946,7 +982,6 @@ zfpm_build_updates (void) hdr = (fpm_msg_hdr_t *) buf; hdr->version = FPM_PROTO_VERSION; - hdr->msg_type = FPM_MSG_TYPE_NETLINK; data = fpm_msg_data (hdr); @@ -966,11 +1001,13 @@ zfpm_build_updates (void) } if (write_msg) { - data_len = zfpm_encode_route (dest, rib, (char *) data, buf_end - data); + data_len = zfpm_encode_route (dest, rib, (char *) data, buf_end - data, + &msg_type); assert (data_len); if (data_len) { + hdr->msg_type = msg_type; msg_len = fpm_data_len_to_msg_len (data_len); hdr->msg_len = htons (msg_len); stream_forward_endp (s, msg_len); @@ -1572,6 +1609,64 @@ DEFUN ( no_fpm_remote_ip, } +/* + * zfpm_init_message_format + */ +static inline void +zfpm_init_message_format (const char *format) +{ + int have_netlink, have_protobuf; + + have_netlink = have_protobuf = 0; + +#ifdef HAVE_NETLINK + have_netlink = 1; +#endif + +#ifdef HAVE_PROTOBUF + have_protobuf = 1; +#endif + + zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; + + if (!format) + { + if (have_netlink) + { + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + } + else if (have_protobuf) + { + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + } + return; + } + + if (!strcmp ("netlink", format)) + { + if (!have_netlink) + { + zlog_err ("FPM netlink message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + return; + } + + if (!strcmp ("protobuf", format)) + { + if (!have_protobuf) + { + zlog_err ("FPM protobuf message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + return; + } + + zlog_warn ("Unknown fpm format '%s'", format); +} + /** * fpm_remote_srv_write * @@ -1601,11 +1696,13 @@ int fpm_remote_srv_write (struct vty *vty ) * * @param[in] port port at which FPM is running. * @param[in] enable TRUE if the zebra FPM module should be enabled + * @param[in] format to use to talk to the FPM. Can be 'netink' or 'protobuf'. * * Returns TRUE on success. */ int -zfpm_init (struct thread_master *master, int enable, uint16_t port) +zfpm_init (struct thread_master *master, int enable, uint16_t port, + const char *format) { static int initialized = 0; @@ -1621,16 +1718,6 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port) zfpm_g->sock = -1; zfpm_g->state = ZFPM_STATE_IDLE; - /* - * Netlink must currently be available for the Zebra-FPM interface - * to be enabled. - */ -#ifndef HAVE_NETLINK - enable = 0; -#endif - - zfpm_g->enabled = enable; - zfpm_stats_init (&zfpm_g->stats); zfpm_stats_init (&zfpm_g->last_ivl_stats); zfpm_stats_init (&zfpm_g->cumulative_stats); @@ -1640,6 +1727,16 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port) install_element (CONFIG_NODE, &fpm_remote_ip_cmd); install_element (CONFIG_NODE, &no_fpm_remote_ip_cmd); + zfpm_init_message_format(format); + + /* + * Disable FPM interface if no suitable format is available. + */ + if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE) + enable = 0; + + zfpm_g->enabled = enable; + if (!enable) { return 1; } |
