* Interval at which we attempt to connect to the FPM.
*/
#define ZFPM_CONNECT_RETRY_IVL 5
-#define FPM_MAX_MAC_MSG_LEN 512
/*
* Sizes of outgoing and incoming stream buffers for writing/reading
* Interval over which we collect statistics.
*/
#define ZFPM_STATS_IVL_SECS 10
+#define FPM_MAX_MAC_MSG_LEN 512
+
+static void zfpm_iterate_rmac_table(struct hash_backet *backet, void *args);
/*
* Structure that holds state for iterating over all route_node
THREAD_WRITE_OFF(zfpm_g->t_write);
}
+static inline void zfpm_connect_off(void)
+{
+ THREAD_TIMER_OFF(zfpm_g->t_connect);
+}
+
/*
* zfpm_conn_up_thread_cb
*
goto done;
}
+ /* Enqueue FPM updates for all the RMAC entries */
+ hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table, NULL);
+
while ((rnode = zfpm_rnodes_iter_next(iter))) {
dest = rib_dest_from_rnode(rnode);
* Start thread to clean up state after the connection goes down.
*/
assert(!zfpm_g->t_conn_down);
- zfpm_debug("Starting conn_down thread");
zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter);
zfpm_g->t_conn_down = NULL;
thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0,
fpm_msg_hdr_t *hdr;
zfpm_g->stats.read_cb_calls++;
- zfpm_g->t_read = NULL;
/*
* Check if async connect is now done.
goto done;
}
- zfpm_debug("Read out a full fpm message");
-
/*
* Just throw it away for now.
*/
/*
* zfpm_writes_pending
*
- * Returns TRUE if we may have something to write to the FPM.
+ * Returns true if we may have something to write to the FPM.
*/
static int zfpm_writes_pending(void)
{
*/
return FPM_GOTO_NEXT_Q;
}
- } while (1);
+ } while (true);
}
/*
case ZFPM_MSG_FORMAT_NONE:
break;
case ZFPM_MSG_FORMAT_NETLINK:
+#ifdef HAVE_NETLINK
+ len = zfpm_netlink_encode_mac(mac, in_buf, in_buf_len);
+ assert(fpm_msg_align(len) == len);
+ *msg_type = FPM_MSG_TYPE_NETLINK;
+#endif /* HAVE_NETLINK */
break;
case ZFPM_MSG_FORMAT_PROTOBUF:
break;
data = fpm_msg_data(hdr);
data_len = zfpm_encode_mac(mac, (char *)data, buf_end - data,
&msg_type);
- /* assert(data_len); */
+ assert(data_len);
hdr->msg_type = msg_type;
msg_len = fpm_data_len_to_msg_len(data_len);
int num_writes;
zfpm_g->stats.write_cb_calls++;
- zfpm_g->t_write = NULL;
/*
* Check if async connect is now done.
int sock, ret;
struct sockaddr_in serv;
- zfpm_g->t_connect = NULL;
assert(zfpm_g->state == ZFPM_STATE_ACTIVE);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
- zfpm_debug("Failed to create socket for connect(): %s",
+ zlog_err("Failed to create socket for connect(): %s",
strerror(errno));
zfpm_g->stats.connect_no_sock++;
return 0;
/*
* zfpm_is_enabled
*
- * Returns TRUE if the zebra FPM module has been enabled.
+ * Returns true if the zebra FPM module has been enabled.
*/
static inline int zfpm_is_enabled(void)
{
/*
* zfpm_conn_is_up
*
- * Returns TRUE if the connection to the FPM is up.
+ * Returns true if the connection to the FPM is up.
*/
static inline int zfpm_conn_is_up(void)
{
if (!fpm_mac)
return 0;
- memcpy(&fpm_mac->zebra_flags, &rmac->flags, sizeof(uint32_t));
-
+ fpm_mac->zebra_flags = rmac->flags;
fpm_mac->vxlan_if = vxlan_if ? vxlan_if->ifindex : 0;
fpm_mac->svi_if = svi_if ? svi_if->ifindex : 0;
return 0;
}
+/*
+ * This function is called when the FPM connections is established.
+ * Iterate over all the RMAC entries for the given L3VNI
+ * and enqueue the RMAC for FPM processing.
+ */
+static void zfpm_trigger_rmac_update_wrapper(struct hash_backet *backet,
+ void *args)
+{
+ zebra_mac_t *zrmac = (zebra_mac_t *)backet->data;
+ zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)args;
+
+ zfpm_trigger_rmac_update(zrmac, zl3vni, false, "RMAC added");
+}
+
+/*
+ * This function is called when the FPM connections is established.
+ * This function iterates over all the L3VNIs to trigger
+ * FPM updates for RMACs currently available.
+ */
+static void zfpm_iterate_rmac_table(struct hash_backet *backet, void *args)
+{
+ zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)backet->data;
+
+ hash_iterate(zl3vni->rmac_table, zfpm_trigger_rmac_update_wrapper,
+ (void *)zl3vni);
+}
+
/*
* zfpm_stats_timer_cb
*/
"FPM protobuf message format is not available");
return;
}
+ flog_warn(EC_ZEBRA_PROTOBUF_NOT_AVAILABLE,
+ "FPM protobuf message format is deprecated and scheduled to be removed. "
+ "Please convert to using netlink format or contact dev@lists.frrouting.org with your use case.");
zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF;
return;
}
* One-time initialization of the Zebra FPM module.
*
* @param[in] port port at which FPM is running.
- * @param[in] enable TRUE if the zebra FPM module should be enabled
+ * @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.
+ * Returns true on success.
*/
static int zfpm_init(struct thread_master *master)
{
/* Create hash table for fpm_mac_info_t enties */
zfpm_g->fpm_mac_info_table = hash_create(zfpm_mac_info_hash_keymake,
- zfpm_mac_info_cmp,
- "FPM MAC info hash table");
+ zfpm_mac_info_cmp,
+ "FPM MAC info hash table");
zfpm_g->sock = -1;
zfpm_g->state = ZFPM_STATE_IDLE;
return 0;
}
+static int zfpm_fini(void)
+{
+ zfpm_write_off();
+ zfpm_read_off();
+ zfpm_connect_off();
+
+ zfpm_stop_stats_timer();
+
+ hook_unregister(rib_update, zfpm_trigger_update);
+ return 0;
+}
+
static int zebra_fpm_module_init(void)
{
hook_register(rib_update, zfpm_trigger_update);
hook_register(zebra_rmac_update, zfpm_trigger_rmac_update);
hook_register(frr_late_init, zfpm_init);
+ hook_register(frr_early_fini, zfpm_fini);
return 0;
}