From 37c92a159c0a55533c27a2e85c571d632eb72624 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Wed, 13 May 2015 11:08:37 +0530 Subject: [PATCH] Increase the maximum supported VRFs to 65k As part of this change, the number of vrfs in vrouter is also made a module load parameter. Also, during soft reset, memory allocated for holding the route tables and for vrf statistics are held on instead of releasing it and allocing it later. Change-Id: I14059031810ae79727b8b0dfa3befcb69703959e Closes-BUG: #1454497 --- dp-core/vr_flow.c | 2 +- dp-core/vr_interface.c | 2 +- dp-core/vr_ip_mtrie.c | 138 +++++++++++++++++++++++++---------------- dp-core/vr_route.c | 53 +++++++++------- dp-core/vrouter.c | 2 +- include/vr_interface.h | 6 +- include/vr_route.h | 3 +- include/vrouter.h | 1 + linux/vrouter_mod.c | 14 +++-- sandesh/vr.sandesh | 4 +- 10 files changed, 134 insertions(+), 91 deletions(-) diff --git a/dp-core/vr_flow.c b/dp-core/vr_flow.c index 4642b3c0a..3b39fc77d 100644 --- a/dp-core/vr_flow.c +++ b/dp-core/vr_flow.c @@ -1055,7 +1055,7 @@ vr_flow_req_is_invalid(struct vrouter *router, vr_flow_req *req, } if (req->fr_flags & VR_FLOW_FLAG_VRFT) { - if ((unsigned short)req->fr_flow_dvrf >= VR_MAX_VRFS) + if ((unsigned short)req->fr_flow_dvrf >= router->vr_max_vrfs) return -EINVAL; } diff --git a/dp-core/vr_interface.c b/dp-core/vr_interface.c index 5603f6cf4..c31979f02 100644 --- a/dp-core/vr_interface.c +++ b/dp-core/vr_interface.c @@ -2077,7 +2077,7 @@ vif_vrf_table_get(struct vr_interface *vif, vr_vrf_assign_req *req) */ int vif_vrf_table_set(struct vr_interface *vif, unsigned int vlan, - short vrf, unsigned short nh_id) + int vrf, unsigned int nh_id) { int ret = 0; diff --git a/dp-core/vr_ip_mtrie.c b/dp-core/vr_ip_mtrie.c index dc243cd19..02380c567 100644 --- a/dp-core/vr_ip_mtrie.c +++ b/dp-core/vr_ip_mtrie.c @@ -13,13 +13,15 @@ #include "vr_datapath.h" #include "vr_ip_mtrie.h" +extern unsigned int vr_vrfs; + extern struct vr_nexthop *ip4_default_nh; static struct vr_vrf_stats **mtrie_vrf_stats; static struct vr_vrf_stats *invalid_vrf_stats; struct vr_nexthop *(*vr_inet_route_lookup)(unsigned int, struct vr_route_req *); -struct vr_vrf_stats *(*vr_inet_vrf_stats)(unsigned short, unsigned int); +struct vr_vrf_stats *(*vr_inet_vrf_stats)(int, unsigned int); static struct ip_mtrie *mtrie_alloc_vrf(unsigned int, unsigned int); @@ -63,7 +65,7 @@ vrfid_to_mtrie(unsigned int vrf_id, unsigned int family) { int index = 0; struct ip_mtrie **mtrie_table; - if (vrf_id >= VR_MAX_VRFS) + if (vrf_id >= vr_vrfs) return NULL; if (family == AF_INET6) @@ -712,9 +714,9 @@ mtrie_delete(struct vr_rtable * _unused, struct vr_route_req *rt) } static inline struct vr_vrf_stats * -mtrie_stats(unsigned short vrf, unsigned int cpu) +mtrie_stats(int vrf, unsigned int cpu) { - if (vrf >= VR_MAX_VRFS) + if ((unsigned int)vrf >= vr_vrfs) return &invalid_vrf_stats[cpu]; if (mtrie_vrf_stats) @@ -722,6 +724,7 @@ mtrie_stats(unsigned short vrf, unsigned int cpu) return NULL; } + static int mtrie_stats_get(vr_vrf_stats_req *req, vr_vrf_stats_req *response) { @@ -777,7 +780,13 @@ mtrie_stats_empty(vr_vrf_stats_req *r) r->vsr_fabric_composites || r->vsr_udp_tunnels || r->vsr_udp_mpls_tunnels || r->vsr_gre_mpls_tunnels || r->vsr_l2_encaps || r->vsr_encaps || r->vsr_gros || - r->vsr_diags) + r->vsr_diags || r->vsr_encap_composites || + r->vsr_evpn_composites || r->vsr_vrf_translates || + r->vsr_vxlan_tunnels || r->vsr_arp_virtual_proxy || + r->vsr_arp_virtual_stitch || r->vsr_arp_virtual_flood || + r->vsr_arp_physical_stitch || r->vsr_arp_tor_proxy || + r->vsr_arp_physical_flood || r->vsr_l2_receives || + r->vsr_uuc_floods) return false; return true; @@ -838,7 +847,7 @@ mtrie_lookup(unsigned int vrf_id, struct vr_route_req *rt) struct ip_bucket_entry *ent; struct vr_nexthop *default_nh, *ret_nh; - default_nh = ip4_default_nh; + default_nh = ip4_default_nh; /* we do not support any thing other than /32 route lookup */ if ((rt->rtr_req.rtr_family == AF_INET) && @@ -990,7 +999,7 @@ mtrie_free_vrf(struct vr_rtable *rtable, unsigned int vrf_id) int i; /* Free V4 and V6 tables */ - for (i=0; i<2; i++) { + for (i = 0; i < 2; i++) { vrf_tables = vn_rtable[i]; mtrie = vrf_tables[vrf_id]; if (!mtrie) @@ -1005,45 +1014,55 @@ mtrie_free_vrf(struct vr_rtable *rtable, unsigned int vrf_id) } static void -mtrie_stats_cleanup(struct vr_rtable *rtable) +mtrie_stats_cleanup(struct vr_rtable *rtable, bool soft_reset) { - unsigned int i; + unsigned int i, stats_memory_size; + stats_memory_size = sizeof(struct vr_vrf_stats) * vr_num_cpus; for (i = 0; i < rtable->algo_max_vrfs; i++) { if (mtrie_vrf_stats[i]) { - vr_free(mtrie_vrf_stats[i]); - mtrie_vrf_stats[i] = NULL; + if (soft_reset) { + memset(mtrie_vrf_stats[i], 0, stats_memory_size); + } else { + vr_free(mtrie_vrf_stats[i]); + mtrie_vrf_stats[i] = NULL; + } } } - vr_free(mtrie_vrf_stats); - rtable->vrf_stats = mtrie_vrf_stats = NULL; + if (!soft_reset) { + vr_free(mtrie_vrf_stats); + rtable->vrf_stats = mtrie_vrf_stats = NULL; - if (invalid_vrf_stats) { - vr_free(invalid_vrf_stats); - invalid_vrf_stats = NULL; + if (invalid_vrf_stats) { + vr_free(invalid_vrf_stats); + invalid_vrf_stats = NULL; + } + } else { + if (invalid_vrf_stats) + memset(invalid_vrf_stats, 0, stats_memory_size); } return; } void -mtrie_algo_deinit(struct vr_rtable *rtable, struct rtable_fspec *fs, bool soft_reset) +mtrie_algo_deinit(struct vr_rtable *rtable, struct rtable_fspec *fs, + bool soft_reset) { unsigned int i; - if (!vn_rtable[0]) - return; - - mtrie_stats_cleanup(rtable); - - for (i = 0; i < fs->rtb_max_vrfs; i++) - mtrie_free_vrf(rtable, i); - - *vn_rtable[0] = *vn_rtable[1] = NULL; + mtrie_stats_cleanup(rtable, soft_reset); + if (rtable->algo_data) { + for (i = 0; i < fs->rtb_max_vrfs; i++) + mtrie_free_vrf(rtable, i); + } - vr_free(rtable->algo_data); - rtable->algo_data = NULL; + if (!soft_reset) { + vn_rtable[0] = vn_rtable[1] = NULL; + vr_free(rtable->algo_data); + rtable->algo_data = NULL; + } algo_init_done = 0; @@ -1054,33 +1073,37 @@ mtrie_algo_deinit(struct vr_rtable *rtable, struct rtable_fspec *fs, bool soft_r static int mtrie_stats_init(struct vr_rtable *rtable) { - int ret = 0, i; + int ret = 0, i = 0; unsigned int stats_memory; - stats_memory = sizeof(void *) * rtable->algo_max_vrfs; - mtrie_vrf_stats = vr_zalloc(stats_memory); - if (!mtrie_vrf_stats) - return vr_module_error(-ENOMEM, __FUNCTION__, - __LINE__, stats_memory); + if (!mtrie_vrf_stats) { + stats_memory = sizeof(void *) * rtable->algo_max_vrfs; + mtrie_vrf_stats = vr_zalloc(stats_memory); + 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); + if (!mtrie_vrf_stats[i] && (ret = -ENOMEM)) { + vr_module_error(ret, __FUNCTION__, __LINE__, i); + goto cleanup; + } + } - 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); - if (!mtrie_vrf_stats[i] && (ret = -ENOMEM)) { - vr_module_error(ret, __FUNCTION__, __LINE__, i); + rtable->vrf_stats = mtrie_vrf_stats; + } + + if (!invalid_vrf_stats) { + invalid_vrf_stats = vr_zalloc(sizeof(struct vr_vrf_stats) * + vr_num_cpus); + if (!invalid_vrf_stats && (ret = -ENOMEM)) { + vr_module_error(ret, __FUNCTION__, __LINE__, -1); goto cleanup; } - } - invalid_vrf_stats = vr_zalloc(sizeof(struct vr_vrf_stats) * - vr_num_cpus); - if (!invalid_vrf_stats && (ret = -ENOMEM)) { - vr_module_error(ret, __FUNCTION__, __LINE__, -1); - goto cleanup; } - rtable->vrf_stats = mtrie_vrf_stats; - return 0; cleanup: @@ -1094,8 +1117,15 @@ mtrie_stats_init(struct vr_rtable *rtable) } } - vr_free(mtrie_vrf_stats); - mtrie_vrf_stats = NULL; + if (mtrie_vrf_stats) { + vr_free(mtrie_vrf_stats); + mtrie_vrf_stats = NULL; + } + + if (invalid_vrf_stats) { + vr_free(invalid_vrf_stats); + invalid_vrf_stats = NULL; + } return ret; } @@ -1109,10 +1139,12 @@ mtrie_algo_init(struct vr_rtable *rtable, struct rtable_fspec *fs) if (algo_init_done) return 0; - table_memory = 2 * sizeof(void *) * fs->rtb_max_vrfs; - rtable->algo_data = vr_zalloc(table_memory); - if (!rtable->algo_data) - return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, table_memory); + if (!rtable->algo_data) { + table_memory = 2 * sizeof(void *) * fs->rtb_max_vrfs; + rtable->algo_data = vr_zalloc(table_memory); + 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))) { diff --git a/dp-core/vr_route.c b/dp-core/vr_route.c index 8fcd830c1..3173b8cf9 100644 --- a/dp-core/vr_route.c +++ b/dp-core/vr_route.c @@ -10,6 +10,8 @@ #include "vr_message.h" #include "vr_sandesh.h" +unsigned int vr_vrfs = VR_DEF_VRFS; + static struct rtable_fspec rtable_families[]; extern int mtrie_algo_init(struct vr_rtable *, struct rtable_fspec *); extern void mtrie_algo_deinit(struct vr_rtable *, struct rtable_fspec *, bool); @@ -19,8 +21,10 @@ extern void bridge_table_deinit(struct vr_rtable *, struct rtable_fspec *, bool) int vr_route_delete(vr_route_req *); int vr_route_get(vr_route_req *); int vr_route_dump(vr_route_req *); + int inet_route_add(struct rtable_fspec *, struct vr_route_req *); int inet_route_del(struct rtable_fspec *, struct vr_route_req *); + int bridge_entry_add(struct rtable_fspec *, struct vr_route_req *); int bridge_entry_del(struct rtable_fspec *, struct vr_route_req *); @@ -361,7 +365,7 @@ inet_route_add(struct rtable_fspec *fs, struct vr_route_req *req) rtable = router->vr_inet_rtable; if (!rtable || - ((unsigned int)req->rtr_req.rtr_vrf_id > fs->rtb_max_vrfs) || + ((unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) || ((unsigned int)(req->rtr_req.rtr_prefix_len) > (RT_IP_ADDR_SIZE(req->rtr_req.rtr_family)*8))) return -EINVAL; @@ -402,7 +406,7 @@ inet_route_del(struct rtable_fspec *fs, struct vr_route_req *req) if (((unsigned int)(req->rtr_req.rtr_prefix_len) > (RT_IP_ADDR_SIZE(req->rtr_req.rtr_family)*8)) || - (unsigned int)(req->rtr_req.rtr_vrf_id) >= VR_MAX_VRFS) + (unsigned int)(req->rtr_req.rtr_vrf_id) >= fs->rtb_max_vrfs) return -EINVAL; router = vrouter_get(req->rtr_req.rtr_rid); @@ -410,7 +414,8 @@ inet_route_del(struct rtable_fspec *fs, struct vr_route_req *req) return -EINVAL; rtable = router->vr_inet_rtable; - if (!rtable || req->rtr_req.rtr_vrf_id >= (int)fs->rtb_max_vrfs) + if (!rtable || + (unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) return -EINVAL; return rtable->algo_del(rtable, req); @@ -420,11 +425,12 @@ static void inet_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, bool soft_reset) { - if (router->vr_inet_rtable) { fs->algo_deinit(router->vr_inet_rtable, fs, soft_reset); - vr_free(router->vr_inet_rtable); - router->vr_inet_rtable = NULL; + if (!soft_reset) { + vr_free(router->vr_inet_rtable); + router->vr_inet_rtable = NULL; + } } return; @@ -438,12 +444,11 @@ inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) if (!fs->algo_init) return 1; - if (router->vr_inet_rtable) - return 0; - - router->vr_inet_rtable = vr_zalloc(sizeof(struct vr_rtable)); - if (!router->vr_inet_rtable) - return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0); + 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) @@ -462,7 +467,7 @@ bridge_entry_add(struct rtable_fspec *fs, struct vr_route_req *req) return -EINVAL; if (!router->vr_bridge_rtable || - ((unsigned int)req->rtr_req.rtr_vrf_id > fs->rtb_max_vrfs) || + ((unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) || ((unsigned int)(req->rtr_req.rtr_mac_size) != VR_ETHER_ALEN)) return -EINVAL; @@ -475,14 +480,15 @@ bridge_entry_del(struct rtable_fspec *fs, struct vr_route_req *req) struct vrouter *router; if ((unsigned int)(req->rtr_req.rtr_mac_size) > 6 || - (unsigned int)(req->rtr_req.rtr_vrf_id) >= VR_MAX_VRFS) + (unsigned int)(req->rtr_req.rtr_vrf_id) >= fs->rtb_max_vrfs) return -EINVAL; router = vrouter_get(req->rtr_req.rtr_rid); if (!router) return -EINVAL; - if (!router->vr_bridge_rtable || req->rtr_req.rtr_vrf_id >= (int)fs->rtb_max_vrfs) + if (!router->vr_bridge_rtable || + (unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) return -EINVAL; return router->vr_bridge_rtable->algo_del(router->vr_bridge_rtable, req); @@ -513,9 +519,8 @@ bridge_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router) static void bridge_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, - bool soft_reset) + bool soft_reset) { - if (!router->vr_bridge_rtable) { return; } @@ -532,7 +537,6 @@ bridge_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, static struct rtable_fspec rtable_families[] = { { .rtb_family = AF_INET, - .rtb_max_vrfs = VR_MAX_VRFS, .rtb_family_init = inet_rtb_family_init, .rtb_family_deinit = inet_rtb_family_deinit, .route_add = inet_route_add, @@ -542,7 +546,6 @@ static struct rtable_fspec rtable_families[] = { }, { .rtb_family = AF_BRIDGE, - .rtb_max_vrfs = VR_MAX_VRFS, .rtb_family_init = bridge_rtb_family_init, .rtb_family_deinit = bridge_rtb_family_deinit, .route_add = bridge_entry_add, @@ -552,7 +555,6 @@ static struct rtable_fspec rtable_families[] = { }, { .rtb_family = AF_INET6, - .rtb_max_vrfs = VR_MAX_VRFS, .rtb_family_init = inet_rtb_family_init, .rtb_family_deinit = inet_rtb_family_deinit, .route_add = inet_route_add, @@ -579,14 +581,19 @@ vr_fib_exit(struct vrouter *router, bool soft_reset) int vr_fib_init(struct vrouter *router) { - int i; - int ret; - int size; + 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); diff --git a/dp-core/vrouter.c b/dp-core/vrouter.c index 152bb7235..22b3d7ac3 100644 --- a/dp-core/vrouter.c +++ b/dp-core/vrouter.c @@ -305,7 +305,7 @@ vrouter_ops_get_process(void *s_req) } resp->vo_interfaces = router->vr_max_interfaces; - resp->vo_vrfs = VR_MAX_VRFS; + resp->vo_vrfs = router->vr_max_vrfs; resp->vo_mpls_labels = router->vr_max_labels; resp->vo_nexthops = router->vr_max_nexthops; resp->vo_bridge_entries = vr_bridge_entries; diff --git a/include/vr_interface.h b/include/vr_interface.h index 7fd07a2ca..d87f559be 100644 --- a/include/vr_interface.h +++ b/include/vr_interface.h @@ -137,8 +137,8 @@ struct vr_interface_driver { }; struct vr_vrf_assign { - short va_vrf; - unsigned short va_nh_id; + int va_vrf; + unsigned int va_nh_id; }; struct vr_interface { @@ -249,7 +249,7 @@ extern void vif_drop_pkt(struct vr_interface *, struct vr_packet *, bool); extern int vif_vrf_table_get(struct vr_interface *, vr_vrf_assign_req *); extern unsigned int vif_vrf_table_get_nh(struct vr_interface *, unsigned short); extern int vif_vrf_table_set(struct vr_interface *, unsigned int, - short, unsigned short); + int, unsigned int); #if defined(__linux__) && defined(__KERNEL__) extern void vr_set_vif_ptr(struct net_device *dev, void *vif); #endif diff --git a/include/vr_route.h b/include/vr_route.h index 4030ef5bd..253cab138 100644 --- a/include/vr_route.h +++ b/include/vr_route.h @@ -11,7 +11,8 @@ extern "C" { #endif #define VR_NUM_ROUTES_PER_DUMP 20 -#define VR_MAX_VRFS 4096 +#define VR_DEF_VRFS 4096 +#define VR_MAX_VRFS 65536 #define METADATA_IP_SUBNET 0xA9FE0000 /* link local subnet (169.254.0.0/16) */ #define METADATA_IP_MASK (0xFFFF << 16) diff --git a/include/vrouter.h b/include/vrouter.h index 423e2cd1b..01e45660e 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -177,6 +177,7 @@ struct vrouter { unsigned int vr_max_labels; struct vr_btable *vr_ilm; + unsigned int vr_max_vrfs; unsigned int vr_max_mirror_indices; struct vr_mirror_entry **vr_mirrors; vr_itable_t vr_mirror_md; diff --git a/linux/vrouter_mod.c b/linux/vrouter_mod.c index eb9a7943f..d50778a74 100644 --- a/linux/vrouter_mod.c +++ b/linux/vrouter_mod.c @@ -37,6 +37,7 @@ extern unsigned int vr_bridge_entries; extern unsigned int vr_bridge_oentries; extern unsigned int vr_mpls_labels; extern unsigned int vr_nexthops; +extern unsigned int vr_vrfs; extern char *ContrailBuildInfo; @@ -2600,14 +2601,15 @@ vrouter_linux_init(void) return ret; } -module_param(vr_flow_entries, int, 0); -module_param(vr_oflow_entries, int, 0); +module_param(vr_flow_entries, uint, 0); +module_param(vr_oflow_entries, uint, 0); -module_param(vr_bridge_entries, int, 0); -module_param(vr_bridge_oentries, int, 0); +module_param(vr_bridge_entries, uint, 0); +module_param(vr_bridge_oentries, uint, 0); -module_param(vr_mpls_labels, int, 0); -module_param(vr_nexthops, int, 0); +module_param(vr_mpls_labels, uint, 0); +module_param(vr_nexthops, uint, 0); +module_param(vr_vrfs, uint, 0); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,32)) module_param(vr_use_linux_br, int, 0); diff --git a/sandesh/vr.sandesh b/sandesh/vr.sandesh index 0ae3b565a..aa8b75d84 100644 --- a/sandesh/vr.sandesh +++ b/sandesh/vr.sandesh @@ -162,7 +162,7 @@ buffer sandesh vr_vrf_assign_req { 1: sandesh_op h_op; 2: i16 var_rid; 3: i16 var_vif_index; - 4: i16 var_vif_vrf; + 4: i32 var_vif_vrf; 5: i16 var_vlan_id; 6: i16 var_marker; 7: i32 var_nh_id; @@ -173,7 +173,7 @@ buffer sandesh vr_vrf_stats_req { 2: i16 vsr_rid; 3: i16 vsr_family; 4: i16 vsr_type; - 5: i16 vsr_vrf; + 5: i32 vsr_vrf; 6: i64 vsr_discards; 7: i64 vsr_resolves; 8: i64 vsr_receives;