/* Return the DPID; exposed to all functions in the module */ indigo_error_t indigo_core_dpid_get(of_dpid_t *dpid) { INIT_CHECK; INDIGO_MEM_COPY(dpid, &ind_core_dpid, sizeof(ind_core_dpid)); return INDIGO_ERROR_NONE; }
indigo_error_t ind_core_serial_num_set(of_serial_num_t serial_num) { if (!ind_core_init_done) { return INDIGO_ERROR_INIT; } INDIGO_MEM_COPY(ind_core_of_config.desc_stats.serial_num, serial_num, OF_SERIAL_NUM_LEN); return INDIGO_ERROR_NONE; }
indigo_error_t ind_core_mfr_desc_set(of_desc_str_t desc) { if (!ind_core_init_done) { return INDIGO_ERROR_INIT; } INDIGO_MEM_COPY(ind_core_of_config.desc_stats.mfr_desc, desc, OF_DESC_STR_LEN); return INDIGO_ERROR_NONE; }
/* Allow the DPID to be set by the configuration */ indigo_error_t indigo_core_dpid_set(of_dpid_t dpid) { if (ind_core_dpid != dpid) { LOG_INFO("Changing switch DPID\n"); INDIGO_MEM_COPY(&ind_core_dpid, &dpid, sizeof(ind_core_dpid)); ind_cxn_reset(IND_CXN_RESET_ALL); } else { LOG_VERBOSE("Switch DPID set called but unchanged\n"); } return INDIGO_ERROR_NONE; }
indigo_error_t ind_core_dp_desc_get(of_desc_str_t desc) { if (!ind_core_init_done) { return INDIGO_ERROR_INIT; } if (desc == NULL) { return INDIGO_ERROR_PARAM; } INDIGO_MEM_COPY(desc, ind_core_of_config.desc_stats.dp_desc, OF_DESC_STR_LEN); return INDIGO_ERROR_NONE; }
indigo_error_t ind_core_init(ind_core_config_t *config) { ft_config_t ft_config; INDIGO_MEM_COPY(&ind_core_config, config, sizeof(*config)); LOG_TRACE("OF state mgr init called"); if (ind_core_init_done) { return INDIGO_ERROR_NONE; } ind_cfg_register(&ind_core_cfg_ops); /* Give some values to desc stats members */ INIT_STR(ind_core_of_config.desc_stats.sw_desc, IND_CORE_SW_DESC_DEFAULT); INIT_STR(ind_core_of_config.desc_stats.hw_desc, IND_CORE_HW_DESC_DEFAULT); INIT_STR(ind_core_of_config.desc_stats.dp_desc, IND_CORE_DP_DESC_DEFAULT); INIT_STR(ind_core_of_config.desc_stats.mfr_desc, IND_CORE_MFR_DESC_DEFAULT); INIT_STR(ind_core_of_config.desc_stats.serial_num, IND_CORE_SERIAL_NUM_DEFAULT); /* Create flow table */ if (config->max_flowtable_entries == 0) { /* Default value */ config->max_flowtable_entries = 16384; } ft_config.strict_match_bucket_count = config->max_flowtable_entries; ft_config.flow_id_bucket_count = config->max_flowtable_entries; if ((ind_core_ft = ft_create(&ft_config)) == NULL) { LOG_ERROR("Unable to allocate flow table\n"); return INDIGO_ERROR_RESOURCE; } ind_core_connection_count = 0; ind_core_init_done = 1; return INDIGO_ERROR_NONE; }
ft_instance_t ft_create(ft_config_t *config) { ft_instance_t ft; int bytes; int idx; /* Allocate the flow table itself */ ft = aim_zmalloc(sizeof(*ft)); INDIGO_MEM_COPY(&ft->config, config, sizeof(ft_config_t)); list_init(&ft->all_list); /* Allocate and init buckets for each search type */ bytes = sizeof(list_head_t) * config->strict_match_bucket_count; ft->strict_match_buckets = aim_zmalloc(bytes); for (idx = 0; idx < config->strict_match_bucket_count; idx++) { list_init(&ft->strict_match_buckets[idx]); } bytes = sizeof(list_head_t) * config->flow_id_bucket_count; ft->flow_id_buckets = aim_zmalloc(bytes); for (idx = 0; idx < config->flow_id_bucket_count; idx++) { list_init(&ft->flow_id_buckets[idx]); } bytes = sizeof(list_head_t) * (1 << FT_COOKIE_PREFIX_LEN); ft->cookie_buckets = aim_zmalloc(bytes); for (idx = 0; idx < (1 << FT_COOKIE_PREFIX_LEN); idx++) { list_init(&ft->cookie_buckets[idx]); } for (idx = 0; idx < FT_MAX_TABLES; idx++) { ft_table_t *table = &ft->tables[idx]; table->checksum_buckets_size = 128; table->checksum_shift = 64 - aim_log2_u32(table->checksum_buckets_size); table->checksum_buckets = aim_zmalloc(table->checksum_buckets_size * sizeof(uint64_t)); } return ft; }
ft_instance_t ft_hash_create(ft_config_t *config) { ft_instance_t ft; int bytes; int idx; if (config->max_entries <= 0) { LOG_ERROR("Hash flow table only supports fixed number of buckets"); return NULL; } /* Allocate the flow table itself */ ft = INDIGO_MEM_ALLOC(sizeof(*ft)); if (ft == NULL) { LOG_ERROR("ERROR: Flow table (hash) creation failed"); return NULL; } INDIGO_MEM_SET(ft, 0, sizeof(*ft)); INDIGO_MEM_COPY(&ft->config, config, sizeof(ft_config_t)); ft->magic = FT_HASH_MAGIC_NUMBER; list_init(&ft->free_list); list_init(&ft->all_list); /* Allocate and init the flow entries */ bytes = sizeof(ft_entry_t) * config->max_entries; ft->flow_entries = INDIGO_MEM_ALLOC(bytes); if (ft->flow_entries == NULL) { LOG_ERROR("ERROR: Flow table (hash) creation failed"); INDIGO_MEM_FREE(ft); return NULL; } INDIGO_MEM_SET(ft->flow_entries, 0, bytes); /* Put the flow entries on the free list */ for (idx = 0; idx < config->max_entries; idx++) { list_push(&ft->free_list, &ft->flow_entries[idx].table_links); } /* Allocate and init buckets for each search type */ bytes = sizeof(list_head_t) * config->prio_bucket_count; ft->prio_buckets = INDIGO_MEM_ALLOC(bytes); if (ft->prio_buckets == NULL) { LOG_ERROR("ERROR: Flow table, prio bucket alloc failed"); ft_hash_delete(ft); return NULL; } INDIGO_MEM_SET(ft->prio_buckets, 0, bytes); for (idx = 0; idx < config->prio_bucket_count; idx++) { list_init(&ft->prio_buckets[idx]); } bytes = sizeof(list_head_t) * config->match_bucket_count; ft->match_buckets = INDIGO_MEM_ALLOC(bytes); if (ft->match_buckets == NULL) { LOG_ERROR("ERROR: Flow table, match bucket alloc failed"); ft_hash_delete(ft); return NULL; } INDIGO_MEM_SET(ft->match_buckets, 0, bytes); for (idx = 0; idx < config->match_bucket_count; idx++) { list_init(&ft->match_buckets[idx]); } bytes = sizeof(list_head_t) * config->flow_id_bucket_count; ft->flow_id_buckets = INDIGO_MEM_ALLOC(bytes); if (ft->flow_id_buckets == NULL) { LOG_ERROR("ERROR: Flow table, flow id bucket alloc failed"); ft_hash_delete(ft); return NULL; } INDIGO_MEM_SET(ft->flow_id_buckets, 0, bytes); for (idx = 0; idx < config->flow_id_bucket_count; idx++) { list_init(&ft->flow_id_buckets[idx]); } return ft; }