#include #include #include #include uint16_t link_db_match_ef(struct link_db_ctx * ctx, struct link_db_match_field * match_field); uint16_t link_db_match_vwire(struct link_db_ctx * ctx, struct link_db_match_field * match_field); uint16_t link_db_match_tera(struct link_db_ctx * ctx, struct link_db_match_field * match_field); typedef uint16_t (*link_db_match_func)(struct link_db_ctx * ctx, struct link_db_match_field * match_field); /* Link db struct */ struct link_db { uint16_t traffic_link_id; union { struct { uint16_t ef_link_id; uint32_t ef_ip_addr; }; uint32_t vwire_id; uint32_t tera_adapter_id; }; }; /* Link db ctx struct */ struct link_db_ctx { uint8_t nr_entries; uint8_t max_entries; enum link_db_type type; struct link_db * link_dbs; link_db_match_func match_func; }; /* Link db ctx item create */ struct link_db_ctx * link_db_create(enum link_db_type type, uint32_t max_entries) { assert((type == LINK_DB_TYPE_EF) || (type == LINK_DB_TYPE_VWIRE) || (type == LINK_DB_TYPE_TERA)); struct link_db_ctx * link_db_ctx = (struct link_db_ctx *)ZMALLOC(sizeof(struct link_db_ctx)); MR_VERIFY_MALLOC(link_db_ctx); link_db_ctx->link_dbs = (struct link_db *)ZMALLOC(sizeof(struct link_db) * max_entries); MR_VERIFY_MALLOC(link_db_ctx->link_dbs); link_db_ctx->max_entries = max_entries; link_db_ctx->nr_entries = 0; link_db_ctx->type = type; if (type == LINK_DB_TYPE_EF) { link_db_ctx->match_func = link_db_match_ef; } else if (type == LINK_DB_TYPE_VWIRE) { link_db_ctx->match_func = link_db_match_vwire; } else if (type == LINK_DB_TYPE_TERA) { link_db_ctx->match_func = link_db_match_tera; } return link_db_ctx; } /* Link db ctx destroy */ void link_db_destroy(struct link_db_ctx ** ctx) { if (*ctx != NULL) { if ((*ctx)->link_dbs != NULL) { FREE((*ctx)->link_dbs); (*ctx)->link_dbs = NULL; (*ctx)->match_func = NULL; } FREE(*ctx); *ctx = NULL; } } /* Link db ctx dump */ void link_db_ctx_dump(struct link_db_ctx * ctx) { assert(ctx != NULL); char str_type[MR_STRING_MAX]; switch (ctx->type) { case LINK_DB_TYPE_EF: snprintf(str_type, sizeof(str_type) - 1, "%u(etherfabric)", ctx->type); break; case LINK_DB_TYPE_VWIRE: snprintf(str_type, sizeof(str_type) - 1, "%u(vwire)", ctx->type); break; case LINK_DB_TYPE_TERA: snprintf(str_type, sizeof(str_type) - 1, "%u(tera)", ctx->type); break; default: snprintf(str_type, sizeof(str_type) - 1, "%u(unknow)", ctx->type); break; } MR_INFO("Link db, max entries:%u, nr entries:%u, type:%s", ctx->max_entries, ctx->nr_entries, str_type); for (int index = 0; index < ctx->nr_entries; index++) { struct link_db * link_db = &ctx->link_dbs[index]; if (ctx->type == LINK_DB_TYPE_EF) { char str_addr[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &link_db->ef_ip_addr, str_addr, sizeof(str_addr)); MR_INFO("Link db, traffic link id:%u, etherfabric link id:%u, etherfabric ip addr:%s", link_db->traffic_link_id, link_db->ef_link_id, str_addr); } else if (ctx->type == LINK_DB_TYPE_VWIRE) { MR_INFO("Link db, traffic link id:%u, vwire id:%u", link_db->traffic_link_id, link_db->vwire_id); } else if (ctx->type == LINK_DB_TYPE_TERA) { MR_INFO("Link db, traffic link id:%u, tera id:%u", link_db->traffic_link_id, link_db->tera_adapter_id); } } } /* Link db config parse */ int link_db_config_parse(const char * cfgfile, struct link_db_ctx * ctx) { assert(ctx != NULL); uint16_t nr_entries = 0; char str_section[MR_STRING_MAX] = {}; for (int index = 0; index < ctx->max_entries; index++) { uint32_t type; snprintf(str_section, sizeof(str_section) - 1, "link_db:%d", index); int ret = MESA_load_profile_uint_nodef(cfgfile, str_section, "type", &type); if ((ret < 0) || (type != ctx->type)) { continue; } struct link_db * link_db = &ctx->link_dbs[nr_entries]; if (type == LINK_DB_TYPE_EF) { uint32_t ef_link_id; ret = MESA_load_profile_uint_nodef(cfgfile, str_section, "ef_link_id", &ef_link_id); if (ret < 0) { MR_ERROR("The : %s ,No config the 'ef_link_id'.", str_section); return RT_ERR; } char str_ef_ip_addr[MR_STRING_MAX] = {}; ret = MESA_load_profile_string_nodef(cfgfile, str_section, "ef_ip_addr", str_ef_ip_addr, sizeof(str_ef_ip_addr)); if (ret < 0) { MR_ERROR("The : %s ,No config the 'ef_ip_addr'.", str_section); return RT_ERR; } uint32_t ef_ip_addr = 0; ret = inet_pton(AF_INET, str_ef_ip_addr, &ef_ip_addr); if (ret < 0) { MR_ERROR("The : %s ,No config the 'ef_ip_addr'.", str_section); return RT_ERR; } link_db->ef_link_id = (uint16_t)ef_link_id; link_db->ef_ip_addr = ef_ip_addr; } else if (type == LINK_DB_TYPE_VWIRE) { uint32_t vwire_id; ret = MESA_load_profile_uint_nodef(cfgfile, str_section, "vwire_id", &vwire_id); if (ret < 0) { MR_ERROR("The : %s ,No config the 'vwire_id'.", str_section); return RT_ERR; } link_db->vwire_id = vwire_id; } else if (type == LINK_DB_TYPE_TERA) { uint32_t tera_adapter_id; ret = MESA_load_profile_uint_nodef(cfgfile, str_section, "tera_adapter_id", &tera_adapter_id); if (ret < 0) { MR_ERROR("The : %s ,No config the 'tera_adapter_id'.", str_section); return RT_ERR; } link_db->tera_adapter_id = tera_adapter_id; } uint32_t traffic_link_id; ret = MESA_load_profile_uint_nodef(cfgfile, str_section, "traffic_link_id", &traffic_link_id); if (ret < 0) { MR_ERROR("The : %s ,No config the 'traffic_link_id'.", str_section); return RT_ERR; } link_db->traffic_link_id = (uint16_t)traffic_link_id; nr_entries++; } ctx->nr_entries = nr_entries; link_db_ctx_dump(ctx); return RT_SUCCESS; } /* Link db match for ef */ uint16_t link_db_match_ef(struct link_db_ctx * ctx, struct link_db_match_field * match_field) { assert(ctx->type == LINK_DB_TYPE_EF); for (int index = 0; index < ctx->nr_entries; index++) { struct link_db * link_db = &ctx->link_dbs[index]; if ((match_field->ef_link_id == link_db->ef_link_id) && (match_field->ef_ip_addr == link_db->ef_ip_addr)) { return link_db->traffic_link_id; } } return UINT16_MAX; } /* Link db match for vwire */ uint16_t link_db_match_vwire(struct link_db_ctx * ctx, struct link_db_match_field * match_field) { assert(ctx->type == LINK_DB_TYPE_VWIRE); for (int index = 0; index < ctx->nr_entries; index++) { struct link_db * link_db = &ctx->link_dbs[index]; if (match_field->vwire_id == link_db->vwire_id) { return link_db->traffic_link_id; } } return UINT16_MAX; } /* Link db match for tera */ uint16_t link_db_match_tera(struct link_db_ctx * ctx, struct link_db_match_field * match_field) { assert(ctx->type == LINK_DB_TYPE_TERA); for (int index = 0; index < ctx->nr_entries; index++) { struct link_db * link_db = &ctx->link_dbs[index]; if (match_field->tera_adapter_id == link_db->tera_adapter_id) { return link_db->traffic_link_id; } } return UINT16_MAX; } /* Link db match */ void link_db_match(struct link_db_ctx * ctx, struct link_db_match_field match_fields[], uint16_t nr_fields, uint16_t result[]) { assert(nr_fields <= 16); for (int index = 0; index < nr_fields; index++) { result[index] = ctx->match_func(ctx, &match_fields[index]); } }