int vr_fragment_table_init(struct vrouter *router) { int num_entries, ret; if (!router->vr_fragment_table) { num_entries = FRAG_TABLE_ENTRIES * FRAG_TABLE_BUCKETS; router->vr_fragment_table = vr_btable_alloc(num_entries, sizeof(struct vr_fragment)); if (!router->vr_fragment_table) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); } if (!router->vr_fragment_otable) { num_entries = FRAG_OTABLE_ENTRIES; router->vr_fragment_otable = vr_btable_alloc(num_entries, sizeof(struct vr_fragment)); if (!router->vr_fragment_otable) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); } if ((ret = vr_fragment_table_scanner_init(router))) return ret; return 0; }
static int inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) { int ret; struct vr_rtable *table = NULL; unsigned int i; for (i = 0; i < RT_MAX; i++) { if (!fs->algo_init[i]) continue; if (vr_get_inet_table(router, i)) continue; table = vr_zalloc(sizeof(struct vr_rtable)); if (!table) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, i); ret = fs->algo_init[i](table, fs); if (ret) return vr_module_error(ret, __FUNCTION__, __LINE__, i); vr_put_inet_table(router, i, table); } return 0; }
static int inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) { int ret; struct vr_rtable *table = NULL; unsigned int i; if (router->vr_inet_rtable || router->vr_inet_mcast_rtable) return vr_module_error(-EEXIST, __FUNCTION__, __LINE__, 0); for (i = 0; i < RT_MAX; i++) { if (fs->algo_init[i]) { table = vr_zalloc(sizeof(struct vr_rtable)); if (!table) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, i); ret = fs->algo_init[i](table, fs); if (ret) return vr_module_error(ret, __FUNCTION__, __LINE__, i); if (i == RT_UCAST) router->vr_inet_rtable = table; if (i == RT_MCAST) router->vr_inet_mcast_rtable = table; } } return 0; }
static int mtrie_stats_init(struct vr_rtable *rtable) { int ret = 0, i = 0; unsigned int stats_memory; if (!mtrie_vrf_stats) { stats_memory = sizeof(void *) * rtable->algo_max_vrfs; mtrie_vrf_stats = vr_zalloc(stats_memory, VR_MTRIE_STATS_OBJECT); if (!mtrie_vrf_stats) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, stats_memory); for (i = 0; i < rtable->algo_max_vrfs; i++) { stats_memory = sizeof(struct vr_vrf_stats) * vr_num_cpus; mtrie_vrf_stats[i] = vr_zalloc(stats_memory, VR_MTRIE_STATS_OBJECT); if (!mtrie_vrf_stats[i] && (ret = -ENOMEM)) { vr_module_error(ret, __FUNCTION__, __LINE__, i); goto cleanup; } } rtable->vrf_stats = mtrie_vrf_stats; } if (!invalid_vrf_stats) { invalid_vrf_stats = vr_zalloc(sizeof(struct vr_vrf_stats) * vr_num_cpus, VR_MTRIE_STATS_OBJECT); if (!invalid_vrf_stats && (ret = -ENOMEM)) { vr_module_error(ret, __FUNCTION__, __LINE__, -1); goto cleanup; } } return 0; cleanup: if (!i) return ret; for (--i; i >= 0; i--) { if (mtrie_vrf_stats[i]) { vr_free(mtrie_vrf_stats[i], VR_MTRIE_STATS_OBJECT); mtrie_vrf_stats[i] = NULL; } } if (mtrie_vrf_stats) { vr_free(mtrie_vrf_stats, VR_MTRIE_STATS_OBJECT); mtrie_vrf_stats = NULL; } if (invalid_vrf_stats) { vr_free(invalid_vrf_stats, VR_MTRIE_STATS_OBJECT); invalid_vrf_stats = NULL; } return ret; }
static int vr_pkt_drop_stats_init(struct vrouter *router) { unsigned int i = 0; unsigned int size = 0; if (router->vr_pdrop_stats) return 0; size = sizeof(void *) * vr_num_cpus; router->vr_pdrop_stats = vr_zalloc(size); if (!router->vr_pdrop_stats) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); goto cleanup; } size = VP_DROP_MAX * sizeof(uint64_t); for (i = 0; i < vr_num_cpus; i++) { router->vr_pdrop_stats[i] = vr_zalloc(size); if (!router->vr_pdrop_stats[i]) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, i); goto cleanup; } } return 0; cleanup: vr_pkt_drop_stats_exit(router); return -ENOMEM; }
static int vr_flow_table_init(struct vrouter *router) { if (!router->vr_flow_table) { if (vr_flow_entries % VR_FLOW_ENTRIES_PER_BUCKET) return vr_module_error(-EINVAL, __FUNCTION__, __LINE__, vr_flow_entries); router->vr_flow_table = vr_btable_alloc(vr_flow_entries, sizeof(struct vr_flow_entry)); if (!router->vr_flow_table) { return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, vr_flow_entries); } } if (!router->vr_oflow_table) { router->vr_oflow_table = vr_btable_alloc(vr_oflow_entries, sizeof(struct vr_flow_entry)); if (!router->vr_oflow_table) { return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, vr_oflow_entries); } } return vr_flow_table_info_init(router); }
int vr_fib_init(struct vrouter *router) { int i = 0, ret, size; struct rtable_fspec *fs; if (vr_vrfs > VR_MAX_VRFS) { return vr_module_error(-EINVAL, __FUNCTION__, __LINE__, vr_vrfs); } router->vr_max_vrfs = vr_vrfs; size = (int)ARRAYSIZE(rtable_families); for (i = 0; i < size; i++) { fs = &rtable_families[i]; fs->rtb_max_vrfs = router->vr_max_vrfs; ret = fs->rtb_family_init(fs, router); if (ret) { vr_module_error(ret, __FUNCTION__, __LINE__, 0); goto exit_init; } } return 0; exit_init: if (!i) return ret; for (--i, --fs; i >= 0; i--) { fs->rtb_family_deinit(fs, router, false); } return ret; }
int mtrie_algo_init(struct vr_rtable *rtable, struct rtable_fspec *fs) { int ret = 0; unsigned int table_memory; if (algo_init_done) return 0; if (!rtable->algo_data) { table_memory = 2 * sizeof(void *) * fs->rtb_max_vrfs; rtable->algo_data = vr_zalloc(table_memory, VR_MTRIE_TABLE_OBJECT); if (!rtable->algo_data) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, table_memory); } rtable->algo_max_vrfs = fs->rtb_max_vrfs; if ((ret = mtrie_stats_init(rtable))) { vr_module_error(ret, __FUNCTION__, __LINE__, 0); goto init_fail; } rtable->algo_add = mtrie_add; rtable->algo_del = mtrie_delete; rtable->algo_lookup = mtrie_lookup; rtable->algo_get = mtrie_get; rtable->algo_dump = mtrie_dump; rtable->algo_stats_get = mtrie_stats_get; rtable->algo_stats_dump = mtrie_stats_dump; vr_inet_vrf_stats = mtrie_stats; /* local cache */ /* ipv4 table */ vn_rtable[0] = (struct ip_mtrie **)rtable->algo_data; /* ipv6 table */ vn_rtable[1] = (struct ip_mtrie **)((unsigned char **)rtable->algo_data + fs->rtb_max_vrfs); mtrie_ip_bkt_info_init(ip4_bkt_info, IP4_PREFIX_LEN); mtrie_ip_bkt_info_init(ip6_bkt_info, IP6_PREFIX_LEN); algo_init_done = 1; return 0; init_fail: if (rtable->algo_data) { vr_free(rtable->algo_data, VR_MTRIE_TABLE_OBJECT); rtable->algo_data = NULL; } return ret; }
int bridge_table_init(struct vr_rtable *rtable, struct rtable_fspec *fs) { /* If table already exists, dont create again */ if (rtable->algo_data) return 0; if (!vr_bridge_oentries) vr_bridge_oentries = ((vr_bridge_entries / 5) + 1023) & ~1023; rtable->algo_data = vr_htable_attach(vrouter_get(0), vr_bridge_entries, vr_bridge_table, vr_bridge_oentries, vr_bridge_otable, sizeof(struct vr_bridge_entry), sizeof(struct vr_bridge_entry_key), 0, bridge_entry_key); if (!rtable->algo_data) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, vr_bridge_entries); /* Max VRF's does not matter as Bridge table is not per VRF. But * still this can be maintained in table */ rtable->algo_max_vrfs = fs->rtb_max_vrfs; rtable->algo_add = bridge_table_add; rtable->algo_del = bridge_table_delete; rtable->algo_lookup = bridge_table_lookup; rtable->algo_get = bridge_table_get; rtable->algo_dump = bridge_table_dump; vr_bridge_lookup = bridge_table_lookup; vn_rtable = rtable->algo_data; return 0; }
int vr_fib_init(struct vrouter *router) { int i; int ret; int size; struct rtable_fspec *fs; size = (int)ARRAYSIZE(rtable_families); for (i = 0; i < size; i++) { fs = &rtable_families[i]; ret = fs->rtb_family_init(fs, router); if (ret) { vr_module_error(ret, __FUNCTION__, __LINE__, i); goto exit_init; } } return 0; exit_init: if (!i) return ret; for (--i, --fs; i >= 0; i--) { fs->rtb_family_deinit(fs, router); } return ret; }
int bridge_table_init(struct vr_rtable *rtable, struct rtable_fspec *fs) { /* If table already exists, dont create again */ if (rtable->algo_data) return 0; rtable->algo_data = vr_htable_create(vr_bridge_entries, vr_bridge_oentries, sizeof(struct vr_bridge_entry), sizeof(struct vr_bridge_entry_key), bridge_entry_valid); if (!rtable->algo_data) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, vr_bridge_entries); /* Max VRF's does not matter as Bridge table is not per VRF. But * still this can be maintained in table */ rtable->algo_max_vrfs = fs->rtb_max_vrfs; rtable->algo_add = bridge_table_add; rtable->algo_del = bridge_table_delete; rtable->algo_lookup = bridge_table_lookup; rtable->algo_get = bridge_table_get; rtable->algo_dump = bridge_table_dump; /* Add the shortcut to lookup routine */ vr_bridge_lookup = bridge_table_lookup; vn_rtable = rtable->algo_data; return 0; }
static struct vr_timer * fragment_table_scanner_init(struct vrouter *router, struct vr_btable *table) { unsigned int num_entries; struct vr_timer *vtimer; struct scanner_params *scanner; if (!table) return NULL; num_entries = vr_btable_entries(table); scanner = vr_zalloc(sizeof(*scanner), VR_FRAGMENT_SCANNER_OBJECT); if (!scanner) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); return NULL; } scanner->sp_router = router; scanner->sp_fragment_table = table; scanner->sp_num_entries = num_entries; scanner->sp_last_scanned_entry = -1; vtimer = vr_malloc(sizeof(*vtimer), VR_TIMER_OBJECT); if (!vtimer) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); goto fail_init; } vtimer->vt_timer = fragment_table_scanner; vtimer->vt_vr_arg = scanner; vtimer->vt_msecs = 1000; if (vr_create_timer(vtimer)) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, num_entries); goto fail_init; } return vtimer; fail_init: if (scanner) vr_free(scanner, VR_FRAGMENT_SCANNER_OBJECT); return NULL; }
static int inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) { int ret; if (!fs->algo_init) return 1; if (!router->vr_inet_rtable) { router->vr_inet_rtable = vr_zalloc(sizeof(struct vr_rtable)); if (!router->vr_inet_rtable) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0); } ret = fs->algo_init(router->vr_inet_rtable, fs); if (ret) return vr_module_error(ret, __FUNCTION__, __LINE__, 0); return 0; }
static int bridge_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) { int ret; struct vr_rtable *table = NULL; if (router->vr_bridge_rtable) return 0; if (fs->algo_init) { table = vr_zalloc(sizeof(struct vr_rtable)); if (!table) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0); ret = fs->algo_init(table, fs); if (ret) return vr_module_error(ret, __FUNCTION__, __LINE__, 0); } router->vr_bridge_rtable = table; return 0; }
int vr_qos_init(struct vrouter *router) { unsigned long size; if (!router->vr_qos_map) { size = vr_qos_map_entries * sizeof(struct vr_forwarding_class *); router->vr_qos_map = vr_zalloc(size, VR_QOS_MAP_OBJECT); if (!router->vr_qos_map) { return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); } } if (!router->vr_fc_table) { size = vr_fc_map_entries * sizeof(struct vr_forwarding_class); router->vr_fc_table = vr_zalloc(size, VR_FC_OBJECT); if (!router->vr_fc_table) { return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); } } return 0; }
int vr_mirror_init(struct vrouter *router) { int ret = 0; unsigned int size; if (!router->vr_mirrors) { router->vr_max_mirror_indices = VR_MAX_MIRROR_INDICES; size = sizeof(struct vr_mirror_entry *) * router->vr_max_mirror_indices; router->vr_mirrors = vr_zalloc(size, VR_MIRROR_TABLE_OBJECT); if (!router->vr_mirrors) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); } if (!router->vr_mirror_md) { router->vr_mirror_md = vr_itable_create(32, 4, 8, 8, 8, 8); if (!router->vr_mirror_md && (ret = -ENOMEM)) { vr_module_error(ret, __FUNCTION__, __LINE__, 0); goto cleanup; } } return 0; cleanup: if (router->vr_mirrors) { vr_free(router->vr_mirrors, VR_MIRROR_TABLE_OBJECT); router->vr_mirrors = NULL; } if (router->vr_mirror_md) { vr_itable_delete(router->vr_mirror_md, vr_mirror_meta_entry_destroy); router->vr_mirror_md = NULL; } return ret; }
int vr_mpls_init(struct vrouter *router) { int ilm_memory; if (!router->vr_ilm) { router->vr_max_labels = VR_MAX_LABELS; ilm_memory = sizeof(struct vr_nexthop *) * router->vr_max_labels; router->vr_ilm = vr_zalloc(ilm_memory); if (!router->vr_ilm) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, ilm_memory); } return 0; }
static int vr_flow_table_info_init(struct vrouter *router) { unsigned int size; struct vr_flow_table_info *infop; if (router->vr_flow_table_info) return 0; size = sizeof(struct vr_flow_table_info) + sizeof(uint32_t) * vr_num_cpus; infop = (struct vr_flow_table_info *)vr_zalloc(size); if (!infop) return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size); router->vr_flow_table_info = infop; router->vr_flow_table_info_size = size; return 0; }
vr_htable_t __vr_htable_create(struct vrouter *router, unsigned int entries, void *htable, unsigned int oentries, void *otable, unsigned int entry_size, unsigned int key_size, unsigned int bucket_size, get_hentry_key get_entry_key) { int i; struct vr_htable *table; vr_hentry_t *ent, *prev; struct iovec iov; if (!entry_size || !entries || !get_entry_key) return NULL; if (!bucket_size) bucket_size = VR_HENTRIES_PER_BUCKET; /* Ceil to near upper number, which is dividable by bucket_size */ entries = ((entries + bucket_size -1) / bucket_size) * bucket_size; table = vr_zalloc(sizeof(struct vr_htable), VR_HTABLE_OBJECT); if (!table) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, sizeof(struct vr_htable)); goto exit; } if (!htable) { table->ht_htable = vr_btable_alloc(entries, entry_size); } else { iov.iov_base = htable; iov.iov_len = entry_size * entries; table->ht_htable = vr_btable_attach(&iov, 1, entry_size); } if (!table->ht_htable) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, entries); goto exit; } if (oentries) { if (!otable) { table->ht_otable = vr_btable_alloc(oentries, entry_size); } else { iov.iov_base = otable; iov.iov_len = entry_size * oentries; table->ht_otable = vr_btable_attach(&iov, 1, entry_size); } if (!table->ht_otable) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, oentries); goto exit; } /* * If there is an over flow table, create the delete data for * main flow table */ i = entries / bucket_size; table->ht_dtable = vr_btable_alloc(i, sizeof(struct vr_hentry_delete_data)); if (!table->ht_dtable) { vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, i); goto exit; } } for (i = 0; i < entries; i++) { ent = vr_btable_get(table->ht_htable, i); ent->hentry_index = i; ent->hentry_next_index = VR_INVALID_HENTRY_INDEX; } prev = NULL; for (i = 0; i < oentries; i++) { ent = vr_btable_get(table->ht_otable, i); ent->hentry_index = entries + i; ent->hentry_next_index = VR_INVALID_HENTRY_INDEX; if (i == 0) table->ht_free_oentry_head = ent; else prev->hentry_next = ent; ent->hentry_flags |= VR_HENTRY_FLAG_IN_FREE_LIST; prev = ent; } table->ht_hentries = entries; table->ht_oentries = oentries; table->ht_entry_size = entry_size; table->ht_key_size = key_size; table->ht_get_key = get_entry_key; table->ht_bucket_size = bucket_size; table->ht_router = router; table->ht_used_oentries = 0; return (vr_htable_t)table; exit: vr_htable_delete((vr_htable_t)table); return NULL; }