From 14776a07636268286a5572dda59dcad09de0ad48 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Fri, 11 Nov 2016 12:02:51 +0530 Subject: [PATCH] Infrastructure to support aging for L2 entries To support aging, there should be . a way to indicate the activity of an entry . a way to easily read/monitor the activity For the first requirement, add packet statistics to each entry. If learning is enabled, the statistics will increment for both source and the destination L2 entries. Else, the statistics will increment only for the destination L2 entry, since no lookup is done for the source. For the second requirement, bridge table is now exposed to applications as a memory block that can be mapped and read like any other memory. This way, the application does not have to send sandesh request for each and every bridge entry just to see whether there is any activity in that entry. Change-Id: I12bb766853580805519bc04d19790bc62853fbef Partial-Bug: #1636413 --- dp-core/vr_bridge.c | 394 +++++++++++------- dp-core/vr_flow.c | 2 +- dp-core/vr_htable.c | 4 +- dp-core/vr_sandesh.c | 24 +- dpdk/dpdk_vrouter.c | 13 +- dpdk/vr_dpdk_host.c | 5 + ...vr_dpdk_flow_mem.c => vr_dpdk_table_mem.c} | 95 +++-- include/nl_util.h | 4 + include/vr_bridge.h | 41 +- include/vr_dpdk.h | 8 +- include/vr_mem.h | 34 ++ include/vr_message.h | 1 + include/vrouter.h | 3 + linux/vr_mem.c | 97 ++++- sandesh/vr.sandesh | 1 + utils/flow.c | 28 +- utils/nl_util.c | 11 + utils/rt.c | 180 ++++++-- utils/vr_util.c | 70 ++++ utils/vtest/sandesh_gen.c | 7 +- 20 files changed, 759 insertions(+), 263 deletions(-) rename dpdk/{vr_dpdk_flow_mem.c => vr_dpdk_table_mem.c} (76%) create mode 100644 include/vr_mem.h diff --git a/dp-core/vr_bridge.c b/dp-core/vr_bridge.c index 2327fc31a..4756a3856 100644 --- a/dp-core/vr_bridge.c +++ b/dp-core/vr_bridge.c @@ -13,31 +13,10 @@ #include "vr_defs.h" #include "vr_hash.h" -struct vr_bridge_entry_key { - unsigned char be_mac[VR_ETHER_ALEN]; - unsigned short be_vrf_id; -}__attribute__((packed)); - -struct vr_bridge_entry; - -struct vr_dummy_bridge_entry { - vr_hentry_t be_hentry; - struct vr_bridge_entry_key be_key; - struct vr_nexthop *be_nh; - uint32_t be_label; - unsigned short be_flags; -} __attribute__((packed)); - -#define VR_BRIDGE_ENTRY_PACK (64 - sizeof(struct vr_dummy_bridge_entry)) - -struct vr_bridge_entry { - vr_hentry_t be_hentry; - struct vr_bridge_entry_key be_key; - struct vr_nexthop *be_nh; - uint32_t be_label; - unsigned short be_flags; - unsigned char be_pack[VR_BRIDGE_ENTRY_PACK]; -} __attribute__((packed)); +#if defined(__linux__) && defined(__KERNEL__) +extern short vr_bridge_table_major; +#endif +unsigned char *vr_bridge_table_path; unsigned int vr_bridge_entries = VR_DEF_BRIDGE_ENTRIES; unsigned int vr_bridge_oentries = 0; @@ -53,6 +32,20 @@ extern struct vr_vrf_stats *(*vr_inet_vrf_stats)(unsigned short, unsigned int); extern l4_pkt_type_t vr_ip_well_known_packet(struct vr_packet *); extern l4_pkt_type_t vr_ip6_well_known_packet(struct vr_packet *); +void *vr_bridge_table, *vr_bridge_otable; + +void * +vr_bridge_get_va(struct vrouter *router, uint64_t offset) +{ + return vr_htable_get_address(vn_rtable, offset); +} + +unsigned int +vr_bridge_table_size(struct vrouter *router) +{ + return vr_htable_size(vn_rtable); +} + bool vr_unknown_uc_flood(struct vr_interface *ingress_vif, struct vr_nexthop *ingress_nh) @@ -94,51 +87,65 @@ vr_find_free_bridge_entry(unsigned int vrf_id, char *mac) return be; } -static int -__bridge_table_add(struct vr_route_req *rt) +static struct vr_bridge_entry * +bridge_add(unsigned int router_id, unsigned int vrf, + uint8_t *mac, int nh_id) { - int ret; - unsigned short flags, i; - struct vr_bridge_entry *be; - struct vr_nexthop *old_nh; struct vr_bridge_entry_key key; + struct vr_nexthop *old_nh; - rt->rtr_req.rtr_label_flags = - VR_BRIDGE_FLAG_MASK(rt->rtr_req.rtr_label_flags); - - VR_MAC_COPY(key.be_mac, rt->rtr_req.rtr_mac); - key.be_vrf_id = rt->rtr_req.rtr_vrf_id; - + VR_MAC_COPY(key.be_mac, mac); + key.be_vrf_id = vrf; be = vr_find_bridge_entry(&key); if (!be) { - be = vr_find_free_bridge_entry(rt->rtr_req.rtr_vrf_id, - (char *)rt->rtr_req.rtr_mac); + be = vr_find_free_bridge_entry(vrf, mac); if (!be) - return -ENOMEM; + return NULL; - VR_MAC_COPY(be->be_key.be_mac, rt->rtr_req.rtr_mac); - be->be_key.be_vrf_id = rt->rtr_req.rtr_vrf_id; + VR_MAC_COPY(be->be_key.be_mac, mac); + be->be_key.be_vrf_id = vrf; + be->be_packets = 0; be->be_flags = VR_BE_VALID_FLAG; } - if (be->be_nh != rt->rtr_nh) { - /* Un ref the old nexthop */ + /* Un ref the old nexthop */ + if (be->be_nh_id != nh_id) { old_nh = be->be_nh; - be->be_nh = vrouter_get_nexthop(rt->rtr_req.rtr_rid, - rt->rtr_req.rtr_nh_id); - if (old_nh) - vrouter_put_nexthop(old_nh); - } else { - /* - * if the nexthop hasn't changed and if the MAC move flag - * has been set, retain the flag - */ + be->be_nh = vrouter_get_nexthop(router_id, nh_id); + if (be->be_nh) { + be->be_nh_id = be->be_nh->nh_id; + } else { + be->be_nh_id = -1; + } + if (be->be_flags & VR_BE_MAC_MOVED_FLAG) { - rt->rtr_req.rtr_label_flags |= VR_BE_MAC_MOVED_FLAG; + be->be_flags &= ~VR_BE_MAC_MOVED_FLAG; } + + if (old_nh) + vrouter_put_nexthop(old_nh); } + return be; +} + +static int +__bridge_table_add(struct vr_route_req *rt) +{ + int ret; + unsigned short flags, i; + + struct vr_bridge_entry *be; + + be = bridge_add(rt->rtr_req.rtr_rid, rt->rtr_req.rtr_vrf_id, + rt->rtr_req.rtr_mac, rt->rtr_req.rtr_nh_id); + if (!be) + return -ENOMEM; + + rt->rtr_req.rtr_label_flags = + VR_BRIDGE_FLAG_MASK(rt->rtr_req.rtr_label_flags); + if (rt->rtr_req.rtr_label_flags & VR_BE_LABEL_VALID_FLAG) be->be_label = rt->rtr_req.rtr_label; @@ -156,6 +163,8 @@ __bridge_table_add(struct vr_route_req *rt) } } + rt->rtr_req.rtr_index = be->be_hentry.hentry_index; + return ret; } @@ -195,6 +204,7 @@ bridge_table_entry_free(vr_htable_t table, vr_hentry_t *hentry, { struct vr_nexthop *nh; struct vr_bridge_entry *be = (struct vr_bridge_entry *)hentry; + if (!be) return; @@ -204,8 +214,11 @@ bridge_table_entry_free(vr_htable_t table, vr_hentry_t *hentry, if (be->be_nh) { nh = be->be_nh; be->be_nh = NULL; + be->be_nh_id = -1; vrouter_put_nexthop(nh); } + + be->be_packets = 0; vr_htable_release_hentry(table, hentry); return; @@ -234,44 +247,81 @@ bridge_table_delete(struct vr_rtable * _unused, struct vr_route_req *rt) return 0; } -static struct vr_nexthop * -bridge_table_lookup(unsigned int vrf_id, struct vr_route_req *rt) +static void +bridge_update_route_req(struct vr_bridge_entry *be, struct vr_route_req *rt) +{ + rt->rtr_req.rtr_label_flags = be->be_flags; + rt->rtr_req.rtr_label = be->be_label; + rt->rtr_nh = be->be_nh; + if (rt->rtr_req.rtr_index != VR_BE_INVALID_INDEX) { + if (rt->rtr_req.rtr_mac) { + VR_MAC_COPY(rt->rtr_req.rtr_mac, be->be_key.be_mac); + } + } else { + rt->rtr_req.rtr_index = be->be_hentry.hentry_index; + } + + return; +} + +static struct vr_bridge_entry * +__bridge_lookup(unsigned int vrf_id, struct vr_route_req *rt) { struct vr_bridge_entry *be; struct vr_bridge_entry_key key; rt->rtr_req.rtr_label_flags = 0; + rt->rtr_nh = NULL; if (rt->rtr_req.rtr_index != VR_BE_INVALID_INDEX) { be = (struct vr_bridge_entry *) vr_htable_get_hentry_by_index(vn_rtable, rt->rtr_req.rtr_index); - if (!be) - return NULL; + } else { + VR_MAC_COPY(key.be_mac, rt->rtr_req.rtr_mac); + key.be_vrf_id = rt->rtr_req.rtr_vrf_id; + be = vr_find_bridge_entry(&key); + } - rt->rtr_req.rtr_label_flags = be->be_flags; - rt->rtr_req.rtr_label = be->be_label; - rt->rtr_nh = be->be_nh; - if (rt->rtr_req.rtr_mac) - VR_MAC_COPY(rt->rtr_req.rtr_mac, be->be_key.be_mac); + return be; +} - return rt->rtr_nh; - } +static struct vr_nexthop * +bridge_table_lookup(unsigned int vrf_id, struct vr_route_req *rt) +{ + struct vr_bridge_entry *be; - rt->rtr_nh = NULL; - rt->rtr_req.rtr_index = VR_BE_INVALID_INDEX; - VR_MAC_COPY(key.be_mac, rt->rtr_req.rtr_mac); - key.be_vrf_id = rt->rtr_req.rtr_vrf_id; + be = __bridge_lookup(vrf_id, rt); + if (be) + bridge_update_route_req(be, rt); - be = vr_find_bridge_entry(&key); - if (be) { - rt->rtr_req.rtr_label_flags = be->be_flags; - rt->rtr_req.rtr_label = be->be_label; - rt->rtr_nh = be->be_nh; - rt->rtr_req.rtr_index = be->be_hentry.hentry_index; + return rt->rtr_nh; +} + +static struct vr_bridge_entry * +bridge_lookup(uint8_t *mac, struct vr_forwarding_md *fmd) +{ + struct vr_route_req rt; + struct vr_bridge_entry *be; + + rt.rtr_req.rtr_label_flags = 0; + rt.rtr_req.rtr_index = VR_BE_INVALID_INDEX; + rt.rtr_req.rtr_mac_size = VR_ETHER_ALEN; + rt.rtr_req.rtr_mac = mac; + /* If multicast L2 packet, use broadcast composite nexthop */ + if (IS_MAC_BMCAST(rt.rtr_req.rtr_mac)) + rt.rtr_req.rtr_mac = (int8_t *)vr_bcast_mac; + rt.rtr_req.rtr_vrf_id = fmd->fmd_dvrf; + be = __bridge_lookup(rt.rtr_req.rtr_vrf_id, &rt); + if (be) + bridge_update_route_req(be, &rt); + + if (fmd && (rt.rtr_req.rtr_label_flags & VR_BE_LABEL_VALID_FLAG)) { + vr_forwarding_md_set_label(fmd, rt.rtr_req.rtr_label, + VR_LABEL_TYPE_UNKNOWN); } - return rt->rtr_nh; + return be; } unsigned short @@ -291,18 +341,10 @@ vr_bridge_route_flags(unsigned int vrf_id, unsigned char *mac) } int -vr_bridge_set_route_flags(unsigned int vrf_id, unsigned char *mac, - unsigned short flags) +vr_bridge_set_route_flags(struct vr_bridge_entry *be, unsigned short flags) { unsigned short be_flags, be_flags_old; - struct vr_bridge_entry *be; - struct vr_bridge_entry_key key; - - VR_MAC_COPY(key.be_mac, mac); - key.be_vrf_id = vrf_id; - - be = vr_find_bridge_entry(&key); if (be) { be_flags = be_flags_old = be->be_flags; if (be_flags & VR_BE_VALID_FLAG) { @@ -468,6 +510,93 @@ bridge_entry_key(vr_htable_t table, vr_hentry_t *entry, unsigned int return &be->be_key; } +#if 0 +static void +vr_bridge_table_data_destroy(vr_bridge_table_data *data) +{ + if (data) { + if (data->btable_file_path) { + vr_free(data->btable_file_path, VR_BRIDGE_TABLE_DATA_OBJECT); + data->btable_file_path = NULL; + } + vr_free(data, VR_BRIDGE_TABLE_DATA_OBJECT); + } + + return; +} + +static vr_bridge_table_data * +vr_bridge_table_data_get(void) +{ + vr_bridge_table_data *data = vr_zalloc(sizeof(vr_bridge_table_data), + VR_BRIDGE_TABLE_DATA_OBJECT); + if (!data) + return NULL; + + if (vr_bridge_table_path) { + data->btable_file_path = vr_zalloc(VR_UNIX_PATH_MAX, + VR_BRIDGE_TABLE_DATA_OBJECT); + if (!data->btable_file_path) { + goto exit_func; + } + } + + return data; + +exit_func: + vr_bridge_table_data_destroy(data); + return NULL; +} + + +void +vr_bridge_table_data_process(void *s_req) +{ + int ret = 0; + struct vrouter *router; + vr_bridge_table_data *resp = NULL, *req = (vr_bridge_table_data *)s_req; + + router = vrouter_get(req->btable_rid); + if (!router) { + ret = -EINVAL; + goto generate_response; + } + + resp = vr_bridge_table_data_get(); + if (!resp) { + ret = -ENOMEM; + goto generate_response; + } + + resp->btable_op = req->btable_op; + switch (req->btable_op) { + case SANDESH_OP_GET: + resp->btable_size = vr_bridge_table_size(router); +#if defined(__linux__) && defined(__KERNEL__) + resp->btable_dev = vr_bridge_table_major; +#endif + if (vr_bridge_table_path) { + strncpy(resp->btable_file_path, vr_bridge_table_path, + VR_UNIX_PATH_MAX - 1); + } + break; + + default: + ret = -EINVAL; + break; + } + +generate_response: + vr_message_response(VR_BRIDGE_TABLE_DATA_OBJECT_ID, resp, ret); + if (resp) { + vr_bridge_table_data_destroy(resp); + resp = NULL; + } + + return; +} +#endif + int bridge_table_init(struct vr_rtable *rtable, struct rtable_fspec *fs) { @@ -479,8 +608,9 @@ bridge_table_init(struct vr_rtable *rtable, struct rtable_fspec *fs) if (!vr_bridge_oentries) vr_bridge_oentries = ((vr_bridge_entries / 5) + 1023) & ~1023; - rtable->algo_data = vr_htable_create(vrouter_get(0), vr_bridge_entries, - vr_bridge_oentries, sizeof(struct vr_bridge_entry), + 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) @@ -575,8 +705,8 @@ vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt, struct vr_eth *eth; struct vr_packet *pkt_c; - struct vr_route_req rtr; - struct vr_nexthop *nh; + struct vr_nexthop *nh = NULL; + struct vr_bridge_entry *be; eth = (struct vr_eth *)pkt_data(pkt); if (!eth) @@ -585,16 +715,17 @@ vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt, if (IS_MAC_BMCAST(eth->eth_smac)) return 0; - rtr.rtr_req.rtr_rid = 0; - rtr.rtr_req.rtr_label_flags = 0; - rtr.rtr_req.rtr_index = VR_BE_INVALID_INDEX; - rtr.rtr_req.rtr_mac_size = VR_ETHER_ALEN; - rtr.rtr_req.rtr_mac = eth->eth_smac; - rtr.rtr_req.rtr_vrf_id = fmd->fmd_dvrf; - nh = vr_bridge_lookup(fmd->fmd_dvrf, &rtr); + be = bridge_lookup(eth->eth_smac, fmd); + if (be) { + nh = be->be_nh; + } + if (!nh) { - rtr.rtr_req.rtr_mac = (int8_t *)vr_bcast_mac; - nh = vr_bridge_lookup(fmd->fmd_dvrf, & rtr); + be = bridge_lookup((uint8_t *)vr_bcast_mac, fmd); + if (be) { + nh = be->be_nh; + } + if (!nh) return 0; @@ -602,24 +733,18 @@ vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt, if (lock < 0) return 0; - rtr.rtr_req.rtr_nh_id = nh->nh_id; - rtr.rtr_req.rtr_label_flags = 0; - rtr.rtr_req.rtr_index = VR_BE_INVALID_INDEX; - rtr.rtr_req.rtr_mac = eth->eth_smac; - ret = bridge_entry_add(NULL, &rtr); - + be = bridge_add(0, fmd->fmd_dvrf, eth->eth_smac, nh->nh_id); bridge_table_unlock(pkt->vp_if, eth->eth_smac, lock); - if (ret) - return ret; + if (!be) + return -ENOMEM; trap_reason = AGENT_TRAP_MAC_LEARN; trap = true; } else { - if (nh->nh_validate_src) { + if (!(be->be_flags & VR_BE_MAC_MOVED_FLAG) && (nh->nh_validate_src)) { valid_src = nh->nh_validate_src(pkt, nh, fmd, NULL); if (valid_src != NH_SOURCE_VALID) { - ret = vr_bridge_set_route_flags(fmd->fmd_dvrf, - rtr.rtr_req.rtr_mac, VR_BE_MAC_MOVED_FLAG); + ret = vr_bridge_set_route_flags(be, VR_BE_MAC_MOVED_FLAG); if (!ret) { /* trap the packet for mac move */ trap_reason = AGENT_TRAP_MAC_MOVE; @@ -630,6 +755,8 @@ vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt, } } + __sync_fetch_and_add(&be->be_packets, 1); + if (trap) { pkt_c = pkt_cow(pkt, 0); if (!pkt_c) { @@ -637,7 +764,8 @@ vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt, ret = -ENOMEM; } - vr_trap(pkt_c, fmd->fmd_dvrf, trap_reason, &rtr.rtr_req.rtr_index); + vr_trap(pkt_c, fmd->fmd_dvrf, + trap_reason, (void *)&be->be_hentry.hentry_index); } return ret; @@ -647,14 +775,14 @@ unsigned int vr_bridge_input(struct vrouter *router, struct vr_packet *pkt, struct vr_forwarding_md *fmd) { - struct vr_route_req rt; - struct vr_forwarding_md cmd; - struct vr_nexthop *nh = NULL; - unsigned short pull_len, overlay_len = VROUTER_OVERLAY_LEN; int reason, handled; - struct vr_vrf_stats *stats; l4_pkt_type_t l4_type = L4_TYPE_UNKNOWN; + unsigned short pull_len, overlay_len = VROUTER_OVERLAY_LEN; + int8_t *dmac; + struct vr_bridge_entry *be; + struct vr_nexthop *nh = NULL; + struct vr_vrf_stats *stats; dmac = (int8_t *) pkt_data(pkt); @@ -730,28 +858,21 @@ vr_bridge_input(struct vrouter *router, struct vr_packet *pkt, } } - rt.rtr_req.rtr_label_flags = 0; - rt.rtr_req.rtr_index = VR_BE_INVALID_INDEX; - rt.rtr_req.rtr_mac_size = VR_ETHER_ALEN; - rt.rtr_req.rtr_mac = dmac; - /* If multicast L2 packet, use broadcast composite nexthop */ - if (IS_MAC_BMCAST(rt.rtr_req.rtr_mac)) - rt.rtr_req.rtr_mac = (int8_t *)vr_bcast_mac; - rt.rtr_req.rtr_vrf_id = fmd->fmd_dvrf; + be = bridge_lookup(dmac, fmd); + if (be) + nh = be->be_nh; - nh = vr_bridge_lookup(fmd->fmd_dvrf, &rt); if (!nh || nh->nh_type == NH_DISCARD) { /* If Flooding of unknown unicast not allowed, drop the packet */ if (!vr_unknown_uc_flood(pkt->vp_if, pkt->vp_nh) || - IS_MAC_BMCAST(rt.rtr_req.rtr_mac)) { + IS_MAC_BMCAST(dmac)) { vr_pfree(pkt, VP_DROP_L2_NO_ROUTE); return 0; } - rt.rtr_req.rtr_mac = (int8_t *)vr_bcast_mac; - rt.rtr_req.rtr_index = VR_BE_INVALID_INDEX; - nh = vr_bridge_lookup(fmd->fmd_dvrf, &rt); + be = bridge_lookup(vr_bcast_mac, fmd); + nh = be->be_nh; if (!nh) { vr_pfree(pkt, VP_DROP_L2_NO_ROUTE); return 0; @@ -764,6 +885,9 @@ vr_bridge_input(struct vrouter *router, struct vr_packet *pkt, pkt->vp_flags |= VP_FLAG_MULTICAST; } + if (be) + __sync_fetch_and_add(&be->be_packets, 1); + if (nh->nh_type != NH_L2_RCV) overlay_len = VROUTER_L2_OVERLAY_LEN; } @@ -790,20 +914,6 @@ vr_bridge_input(struct vrouter *router, struct vr_packet *pkt, } } - - /* - * If there is a label attached to this bridge entry add the - * label - */ - if (rt.rtr_req.rtr_label_flags & VR_BE_LABEL_VALID_FLAG) { - if (!fmd) { - vr_init_forwarding_md(&cmd); - fmd = &cmd; - } - vr_forwarding_md_set_label(fmd, rt.rtr_req.rtr_label, - VR_LABEL_TYPE_UNKNOWN); - } - if (pull_len && !pkt_push(pkt, pull_len)) { vr_pfree(pkt, VP_DROP_PUSH); return 0; diff --git a/dp-core/vr_flow.c b/dp-core/vr_flow.c index 47490fbb2..86d7aff83 100644 --- a/dp-core/vr_flow.c +++ b/dp-core/vr_flow.c @@ -43,7 +43,7 @@ unsigned char *vr_flow_path; unsigned int vr_flow_hold_limit = VR_DEF_MAX_FLOW_TABLE_HOLD_COUNT; #if defined(__linux__) && defined(__KERNEL__) -extern unsigned short vr_flow_major; +extern short vr_flow_major; #endif uint32_t vr_hashrnd = 0; diff --git a/dp-core/vr_htable.c b/dp-core/vr_htable.c index 1eddc05fe..d8b5d9d19 100644 --- a/dp-core/vr_htable.c +++ b/dp-core/vr_htable.c @@ -156,7 +156,7 @@ vr_htable_get_hentry_by_index(vr_htable_t htable, unsigned int index) vr_hentry_t *ent; ent = __vr_htable_get_hentry_by_index(htable, index); - if(ent && (ent->hentry_flags & VR_HENTRY_FLAG_VALID)) + if (ent && (ent->hentry_flags & VR_HENTRY_FLAG_VALID)) return ent; return NULL; @@ -586,7 +586,7 @@ vr_htable_find_hentry(vr_htable_t htable, void *key, unsigned int key_len) return ent; } - for(o_ent = ent->hentry_next; o_ent; o_ent = o_ent->hentry_next) { + for (o_ent = ent->hentry_next; o_ent; o_ent = o_ent->hentry_next) { /* Though in the list, can be under the deletion */ if (!(o_ent->hentry_flags & VR_HENTRY_FLAG_VALID)) diff --git a/dp-core/vr_sandesh.c b/dp-core/vr_sandesh.c index 177152aea..f135beeca 100644 --- a/dp-core/vr_sandesh.c +++ b/dp-core/vr_sandesh.c @@ -40,15 +40,15 @@ struct sandesh_object_md sandesh_md[] = { .obj_len = 4 * sizeof(vr_flow_req), .obj_type_string = "vr_flow_req", }, - [VR_VRF_ASSIGN_OBJECT_ID] = { + [VR_VRF_ASSIGN_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_vrf_assign_req), .obj_type_string = "vr_vrf_assign_req", }, - [VR_VRF_STATS_OBJECT_ID] = { + [VR_VRF_STATS_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_vrf_stats_req), .obj_type_string = "vr_vrf_stats_req", }, - [VR_DROP_STATS_OBJECT_ID] = { + [VR_DROP_STATS_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_drop_stats_req), .obj_type_string = "vr_drop_stats_req", }, @@ -56,11 +56,11 @@ struct sandesh_object_md sandesh_md[] = { .obj_len = 4 * sizeof(vr_response), .obj_type_string = "vr_response", }, - [VR_VXLAN_OBJECT_ID] = { + [VR_VXLAN_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_vxlan_req), .obj_type_string = "vr_vxlan_req", }, - [VR_VROUTER_OPS_OBJECT_ID] = { + [VR_VROUTER_OPS_OBJECT_ID] = { .obj_len = 4 * sizeof(vrouter_ops), .obj_type_string = "vrouter_ops", }, @@ -69,23 +69,29 @@ struct sandesh_object_md sandesh_md[] = { (VR_FLOW_MAX_CPUS * sizeof(unsigned int))), .obj_type_string = "vr_flow_table_data", }, - [VR_MEM_STATS_OBJECT_ID] = { + [VR_MEM_STATS_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_mem_stats_req), .obj_type_string = "vr_mem_stats_req", }, - [VR_QOS_MAP_OBJECT_ID] = { + [VR_QOS_MAP_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_qos_map_req), .obj_get_size = vr_qos_map_req_get_size, .obj_type_string = "vr_qos_map_req", }, - [VR_FC_MAP_OBJECT_ID] = { + [VR_FC_MAP_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_fc_map_req), .obj_type_string = "vr_fc_map_req", }, [VR_FLOW_RESPONSE_OBJECT_ID] = { .obj_len = 4 * sizeof(vr_flow_response), - .obj_type_string = "vr_flow_response", + .obj_type_string = "vr_flow_response", }, +#if 0 + [VR_BRIDGE_TABLE_DATA_OBJECT_ID] = { + .obj_len = 4 * sizeof(vr_bridge_table_data), + .obj_type_string = "vr_bridge_table_data", + }, +#endif }; static unsigned int diff --git a/dpdk/dpdk_vrouter.c b/dpdk/dpdk_vrouter.c index 51a85098f..78163c8b3 100644 --- a/dpdk/dpdk_vrouter.c +++ b/dpdk/dpdk_vrouter.c @@ -27,6 +27,7 @@ #include "vr_dpdk_virtio.h" #include "vr_uvhost.h" #include "vr_bridge.h" +#include "vr_mem.h" #include "nl_util.h" #include @@ -636,13 +637,23 @@ dpdk_init(void) version_print(); - ret = vr_dpdk_flow_mem_init(); + ret = vr_dpdk_table_mem_init(VR_MEM_FLOW_TABLE_OBJECT, vr_flow_entries, + VR_FLOW_TABLE_SIZE, vr_oflow_entries, VR_OFLOW_TABLE_SIZE); if (ret < 0) { RTE_LOG(ERR, VROUTER, "Error initializing flow table: %s (%d)\n", rte_strerror(-ret), -ret); return ret; } + ret = vr_dpdk_table_mem_init(VR_MEM_BRIDGE_TABLE_OBJECT, vr_bridge_entries, + VR_BRIDGE_TABLE_SIZE, vr_bridge_oentries, + VR_BRIDGE_OFLOW_TABLE_SIZE); + if (ret < 0) { + RTE_LOG(ERR, VROUTER, "Error initializing bridge table: %s (%d)\n", + rte_strerror(-ret), -ret); + return ret; + } + ret = dpdk_argv_update(); if (ret == -1) { RTE_LOG(ERR, VROUTER, "Error updating EAL arguments\n"); diff --git a/dpdk/vr_dpdk_host.c b/dpdk/vr_dpdk_host.c index 78474220d..e46947c28 100644 --- a/dpdk/vr_dpdk_host.c +++ b/dpdk/vr_dpdk_host.c @@ -1444,9 +1444,14 @@ vr_dpdk_host_init(void) if (!vrouter_host) { vrouter_host = vrouter_get_host(); + if (vr_dpdk_flow_init()) { return -1; } + + if (vr_dpdk_bridge_init()) { + return -1; + } } /* diff --git a/dpdk/vr_dpdk_flow_mem.c b/dpdk/vr_dpdk_table_mem.c similarity index 76% rename from dpdk/vr_dpdk_flow_mem.c rename to dpdk/vr_dpdk_table_mem.c index 92d0e9973..e2ecd39fd 100644 --- a/dpdk/vr_dpdk_flow_mem.c +++ b/dpdk/vr_dpdk_table_mem.c @@ -14,6 +14,7 @@ #include "vr_dpdk.h" #include "vr_btable.h" +#include "vr_mem.h" #include "nl_util.h" #include @@ -29,9 +30,9 @@ struct vr_hugepage_info { uint32_t num_pages; } vr_hugepage_md[HPI_MAX]; -extern void *vr_flow_table; -extern void *vr_oflow_table; -extern unsigned char *vr_flow_path; +extern void *vr_flow_table, *vr_oflow_table; +extern void *vr_bridge_table, *vr_bridge_otable; +extern unsigned char *vr_flow_path, *vr_bridge_table_path; static int vr_hugepage_info_init(void) @@ -135,24 +136,54 @@ vr_hugepage_info_init(void) return 0; } + int -vr_dpdk_flow_mem_init(void) +vr_dpdk_table_mem_init(unsigned int table, unsigned int entries, + unsigned long size, unsigned int oentries, unsigned long osize) { int ret, i, fd; - size_t size, flow_table_size; - struct vr_hugepage_info *hpi; + + void **table_p; + char shm_file[VR_UNIX_PATH_MAX]; char *file_name, *touse_file_name = NULL; + char *shmem_name, *hp_file_name; + unsigned char **path; + struct stat f_stat; - char shm_file[VR_UNIX_PATH_MAX]; + struct vr_hugepage_info *hpi; - if (!vr_oflow_entries) - vr_oflow_entries = ((vr_flow_entries / 5) + 1023) & ~1023; + if (!oentries) { + oentries = (entries / 5 + 1023) & ~1023; + osize = (size / entries) * oentries; + } - flow_table_size = VR_FLOW_TABLE_SIZE + VR_OFLOW_TABLE_SIZE; + size += osize; + + switch (table) { + case VR_MEM_FLOW_TABLE_OBJECT: + shmem_name = "flow.shmem"; + hp_file_name = "flow"; + table_p = &vr_dpdk.flow_table; + path = &vr_flow_path; + vr_oflow_entries = oentries; + break; + + case VR_MEM_BRIDGE_TABLE_OBJECT: + shmem_name = "bridge.shmem"; + hp_file_name = "bridge"; + table_p = &vr_dpdk.bridge_table; + path = &vr_bridge_table_path; + vr_bridge_oentries = oentries; + break; + + default: + return -EINVAL; + } if (no_huge_set) { /* Create a shared memory under the socket directory. */ - ret = snprintf(shm_file, sizeof(shm_file), "%s/flow.shmem", vr_socket_dir); + ret = snprintf(shm_file, sizeof(shm_file), "%s/%s", + vr_socket_dir, shmem_name); if (ret >= sizeof(shm_file)) { RTE_LOG(ERR, VROUTER, "Error creating shared memory file\n"); return -ENOMEM; @@ -170,12 +201,11 @@ vr_dpdk_flow_mem_init(void) hpi = &vr_hugepage_md[i]; if (!hpi->mnt) continue; - file_name = malloc(strlen(hpi->mnt) + strlen("/flow") + 1); - sprintf(file_name, "%s/flow", hpi->mnt); + file_name = malloc(strlen(hpi->mnt) + strlen(hp_file_name) + 1); + sprintf(file_name, "%s/%s", hpi->mnt, hp_file_name); if (stat(file_name, &f_stat) == -1) { if (!touse_file_name) { - size = hpi->size; - if (size >= flow_table_size) { + if (hpi->size >= size) { touse_file_name = file_name; } else { free(file_name); @@ -196,33 +226,40 @@ vr_dpdk_flow_mem_init(void) touse_file_name, rte_strerror(errno), errno); return -errno; } - if (no_huge_set){ - ret = ftruncate(fd, flow_table_size); + + if (no_huge_set) { + ret = ftruncate(fd, size); if (ret == -1) { RTE_LOG(ERR, VROUTER, "Error truncating file %s: %s (%d)\n", touse_file_name, rte_strerror(errno), errno); return -errno; } } - vr_dpdk.flow_table = mmap(NULL, flow_table_size, PROT_READ | PROT_WRITE, + + *table_p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); /* the file descriptor is no longer needed */ close(fd); - if (vr_dpdk.flow_table == MAP_FAILED) { + if (*table_p == MAP_FAILED) { RTE_LOG(ERR, VROUTER, "Error mmapping file %s: %s (%d)\n", touse_file_name, rte_strerror(errno), errno); return -errno; } - memset(vr_dpdk.flow_table, 0, flow_table_size); - vr_flow_path = (unsigned char *)touse_file_name; + memset(*table_p, 0, size); + *path = (unsigned char *)touse_file_name; } - if (!vr_dpdk.flow_table) - return -ENOMEM; + return 0; +} - vr_flow_hold_limit = VR_DPDK_MAX_FLOW_TABLE_HOLD_COUNT; - RTE_LOG(INFO, VROUTER, "Max HOLD flow entries set to %u\n", - vr_flow_hold_limit); +int +vr_dpdk_bridge_init(void) +{ + if (!vr_dpdk.bridge_table) + return -1; + + vr_bridge_table = vr_dpdk.bridge_table; + vr_bridge_otable = vr_dpdk.bridge_table + VR_BRIDGE_TABLE_SIZE; return 0; } @@ -230,6 +267,8 @@ vr_dpdk_flow_mem_init(void) int vr_dpdk_flow_init(void) { + if (!vr_dpdk.flow_table) + return -1; vr_flow_table = vr_dpdk.flow_table; vr_oflow_table = vr_dpdk.flow_table + VR_FLOW_TABLE_SIZE; @@ -237,5 +276,9 @@ vr_dpdk_flow_init(void) if (!vr_flow_table) return -1; + vr_flow_hold_limit = VR_DPDK_MAX_FLOW_TABLE_HOLD_COUNT; + RTE_LOG(INFO, VROUTER, "Max HOLD flow entries set to %u\n", + vr_flow_hold_limit); + return 0; } diff --git a/include/nl_util.h b/include/nl_util.h index fef822a57..9540988a5 100644 --- a/include/nl_util.h +++ b/include/nl_util.h @@ -29,6 +29,9 @@ extern "C" { #define VR_NETLINK_PROTO_DEFAULT -1 #define VR_NETLINK_PROTO_TEST -2 +#define BRIDGE_TABLE_DEV "/dev/vr_bridge" +#define FLOW_TABLE_DEV "/dev/flow" + struct nl_response { uint8_t *nl_data; unsigned int nl_type; @@ -151,6 +154,7 @@ extern struct nl_client *vr_get_nl_client(int); extern int vr_response_common_process(vr_response *, bool *); +extern void *vr_table_map(int, unsigned int, char *, size_t); extern unsigned long vr_sum_drop_stats(vr_drop_stats_req *); extern void vr_drop_stats_req_destroy(vr_drop_stats_req *); extern vr_drop_stats_req *vr_drop_stats_req_get_copy(vr_drop_stats_req *); diff --git a/include/vr_bridge.h b/include/vr_bridge.h index 99a9b7f3f..4f0403193 100644 --- a/include/vr_bridge.h +++ b/include/vr_bridge.h @@ -5,7 +5,7 @@ #define __VR_BRIDGE_H__ #include "vr_defs.h" -#include "vrouter.h" +#include "vr_htable.h" #define VR_DEF_BRIDGE_ENTRIES (256 * 1024) @@ -41,9 +41,48 @@ #define VR_BE_INVALID_INDEX ((unsigned int)-1) +struct vr_bridge_entry_key { + unsigned char be_mac[VR_ETHER_ALEN]; + unsigned short be_vrf_id; +}__attribute__((packed)); + +struct vr_bridge_entry; + +struct vr_dummy_bridge_entry { + vr_hentry_t be_hentry; + struct vr_bridge_entry_key be_key; + struct vr_nexthop *be_nh; + uint64_t be_packets; + uint32_t be_label; + uint32_t be_nh_id; + unsigned short be_flags; +} __attribute__((packed)); + +#define VR_BRIDGE_ENTRY_PACK (64 - sizeof(struct vr_dummy_bridge_entry)) + +struct vr_bridge_entry { + vr_hentry_t be_hentry; + struct vr_bridge_entry_key be_key; + struct vr_nexthop *be_nh; + uint64_t be_packets; + uint32_t be_label; + int32_t be_nh_id; + unsigned short be_flags; + unsigned char be_pack[VR_BRIDGE_ENTRY_PACK]; +} __attribute__((packed)); + + +extern unsigned int vr_bridge_entries, vr_bridge_oentries; +#define VR_BRIDGE_TABLE_SIZE (vr_bridge_entries *\ + sizeof(struct vr_bridge_entry)) +#define VR_BRIDGE_OFLOW_TABLE_SIZE (vr_bridge_oentries *\ + sizeof(struct vr_bridge_entry)) + extern char vr_bcast_mac[]; unsigned int vr_bridge_table_used_oflow_entries(struct vrouter *); unsigned int vr_bridge_table_used_total_entries(struct vrouter *); +void *vr_bridge_get_va(struct vrouter *, uint64_t); +unsigned int vr_bridge_table_size(struct vrouter *); #endif diff --git a/include/vr_dpdk.h b/include/vr_dpdk.h index bd031b6d1..284817b3c 100644 --- a/include/vr_dpdk.h +++ b/include/vr_dpdk.h @@ -505,6 +505,7 @@ struct vr_dpdk_global { /* NetLink socket handler */ void *netlink_sock; void *flow_table; + void *bridge_table; /* Packet socket */ void *packet_transport; /* Interface configuration mutex @@ -647,11 +648,10 @@ uint64_t vr_dpdk_ethdev_rx_emulate(struct vr_interface *vif, /* Check if port_id is a bond slave. */ bool vr_dpdk_ethdev_bond_port_match(uint8_t port_id, struct vr_dpdk_ethdev *ethdev); -/* - * vr_dpdk_flow_mem.c - */ -int vr_dpdk_flow_mem_init(void); +int vr_dpdk_table_mem_init(unsigned int, unsigned int, unsigned long, + unsigned int, unsigned long); int vr_dpdk_flow_init(void); +int vr_dpdk_bridge_init(void); /* * vr_dpdk_host.c diff --git a/include/vr_mem.h b/include/vr_mem.h new file mode 100644 index 000000000..3c42aaa85 --- /dev/null +++ b/include/vr_mem.h @@ -0,0 +1,34 @@ +/* + * vr_mem.h -- table map definitions + * + * Copyright(c) 2016, Juniper Networks, Inc. + * All rights reserved + */ +#ifndef __VR_MEM_H__ +#define __VR_MEM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define VR_MEM_FLOW_TABLE_OBJECT 0 +#define VR_MEM_BRIDGE_TABLE_OBJECT 1 +#define VR_MEM_MAX_OBJECT 2 + +struct vr_mem_object { + struct vrouter *vmo_router; + unsigned int vmo_object_type; +}; + +#define MEM_DEV_MINOR_START 0 +#define MEM_DEV_NUM_DEVS 2 + +#define ROUTER_FROM_MINOR(minor) (((minor) >> 7) & 0xFF) +#define OBJECT_FROM_MINOR(minor) ((minor) & 0x7F) + +#ifdef __cplusplus +} +#endif + +#endif /* __VR_MEM_H__ */ diff --git a/include/vr_message.h b/include/vr_message.h index 999e8409d..36adf9a88 100644 --- a/include/vr_message.h +++ b/include/vr_message.h @@ -33,6 +33,7 @@ #define VR_QOS_MAP_OBJECT_ID 15 #define VR_FC_MAP_OBJECT_ID 16 #define VR_FLOW_RESPONSE_OBJECT_ID 17 +#define VR_BRIDGE_TABLE_DATA_OBJECT_ID 18 #define VR_MESSAGE_PAGE_SIZE (4096 - 128) diff --git a/include/vrouter.h b/include/vrouter.h index ff36e5339..bf91667f5 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -15,6 +15,7 @@ extern "C" { #include "vr_interface.h" #include "vr_qos.h" #include "vr_flow.h" +#include "vr_bridge.h" #include "vr_interface.h" #include "vr_nexthop.h" #include "vr_route.h" @@ -46,6 +47,7 @@ extern unsigned int vr_num_cpus; enum vr_malloc_objects_t { VR_ASSEMBLER_TABLE_OBJECT, VR_BRIDGE_MAC_OBJECT, + VR_BRIDGE_TABLE_DATA_OBJECT, VR_BTABLE_OBJECT, VR_BUILD_INFO_OBJECT, VR_DEFER_OBJECT, @@ -86,6 +88,7 @@ enum vr_malloc_objects_t { VR_MESSAGE_OBJECT, VR_MESSAGE_RESPONSE_OBJECT, VR_MESSAGE_DUMP_OBJECT, + VR_MEM_OBJECT, VR_MEM_STATS_REQ_OBJECT, VR_MIRROR_OBJECT, VR_MIRROR_TABLE_OBJECT, diff --git a/linux/vr_mem.c b/linux/vr_mem.c index 9014a9f31..81980d6f7 100644 --- a/linux/vr_mem.c +++ b/linux/vr_mem.c @@ -14,25 +14,46 @@ #include #include "vrouter.h" +#include "vr_mem.h" + +#define MEM_DEV_MINOR_START 0 +#define MEM_DEV_NUM_DEVS 2 -#define MEM_DEV_MINOR_START 0 -#define MEM_DEV_NUM_DEVS 1 short vr_flow_major = -1; +short vr_bridge_table_major = -1; + static dev_t mem_dev; struct cdev *mem_cdev; static int mem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - struct vrouter *router = (struct vrouter *)vma->vm_private_data; + void *va; + struct vr_mem_object *vmo = (struct vr_mem_object *)vma->vm_private_data; + struct vrouter *router = vmo->vmo_router; struct page *page; pgoff_t offset; offset = vmf->pgoff; - page = virt_to_page(vr_flow_get_va(router, offset << PAGE_SHIFT)); + + switch (vmo->vmo_object_type) { + case VR_MEM_FLOW_TABLE_OBJECT: + va = vr_flow_get_va(router, offset << PAGE_SHIFT); + break; + + case VR_MEM_BRIDGE_TABLE_OBJECT: + va = vr_bridge_get_va(router, offset << PAGE_SHIFT); + break; + + default: + return -EFAULT; + } + + page = virt_to_page(va); get_page(page); vmf->page = page; + return 0; } @@ -43,23 +64,33 @@ static struct vm_operations_struct mem_vm_ops = { static int mem_dev_mmap(struct file *fp, struct vm_area_struct *vma) { - struct vrouter *router = (struct vrouter *)fp->private_data; - unsigned long size, flow_table_size; - - if (!router) - return -ENOMEM; + struct vr_mem_object *vmo = (struct vr_mem_object *)fp->private_data; + struct vrouter *router = vmo->vmo_router; + unsigned long size, table_size; size = vma->vm_end - vma->vm_start; - flow_table_size = vr_flow_table_size(router); - if (size > flow_table_size) + switch (vmo->vmo_object_type) { + case VR_MEM_FLOW_TABLE_OBJECT: + table_size = vr_flow_table_size(router); + break; + + case VR_MEM_BRIDGE_TABLE_OBJECT: + table_size = vr_bridge_table_size(router); + break; + + default: + return -EINVAL; + } + + if (size > table_size) return -EINVAL; if (vma->vm_pgoff + (size >> PAGE_SHIFT) > - (flow_table_size >> PAGE_SHIFT)) + (table_size >> PAGE_SHIFT)) return -EINVAL; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_private_data = (void *)router; + vma->vm_private_data = (void *)vmo; vma->vm_ops = &mem_vm_ops; return 0; @@ -68,10 +99,12 @@ mem_dev_mmap(struct file *fp, struct vm_area_struct *vma) static int mem_dev_release(struct inode *inode, struct file *filp) { - struct vrouter *router = (struct vrouter *)filp->private_data; + struct vr_mem_object *vmo = (struct vr_mem_object *)filp->private_data; - if (router) + if (vmo) { + vr_free(vmo, VR_MEM_OBJECT); filp->private_data = NULL; + } return 0; } @@ -80,13 +113,39 @@ static int mem_dev_open(struct inode *inode, struct file *filp) { dev_t dev = inode->i_rdev; + int ret = 0; unsigned int minor = MINOR(dev); + unsigned int router_id = ROUTER_FROM_MINOR(minor); + unsigned int object_id = OBJECT_FROM_MINOR(minor); - filp->private_data = (void *)vrouter_get(minor); - if (!filp->private_data) + struct vr_mem_object *vmo; + + if (object_id > VR_MEM_MAX_OBJECT) return -EINVAL; + vmo = vr_malloc(sizeof(*vmo), VR_MEM_OBJECT); + if (!vmo) + return -ENOMEM; + + vmo->vmo_router = (void *)vrouter_get(router_id); + if (!vmo->vmo_router) { + ret = -EINVAL; + goto fail; + } + + vmo->vmo_object_type = object_id; + + filp->private_data = vmo; + return 0; + +fail: + if (vmo) { + vr_free(vmo, VR_MEM_OBJECT); + vmo = NULL; + } + + return ret; } struct file_operations mdev_ops = { @@ -114,7 +173,7 @@ vr_mem_init(void) int ret; ret = alloc_chrdev_region(&mem_dev, MEM_DEV_MINOR_START, - MEM_DEV_NUM_DEVS, "flow"); + MEM_DEV_NUM_DEVS, "vrouter_mem"); if (ret < 0) { printk("%s:%d Device number reservation failed with return %d\n", __FUNCTION__, __LINE__, ret); @@ -136,7 +195,7 @@ vr_mem_init(void) goto init_fail; } - vr_flow_major = MAJOR(mem_dev); + vr_flow_major = vr_bridge_table_major = MAJOR(mem_dev); return ret; diff --git a/sandesh/vr.sandesh b/sandesh/vr.sandesh index 6df3cb161..d8926a20d 100644 --- a/sandesh/vr.sandesh +++ b/sandesh/vr.sandesh @@ -454,3 +454,4 @@ buffer sandesh vr_flow_table_data { 14: u32 ftable_oflow_entries; 15: list ftable_hold_stat; } + diff --git a/utils/flow.c b/utils/flow.c index 154f2f01e..9eb124b93 100644 --- a/utils/flow.c +++ b/utils/flow.c @@ -45,6 +45,7 @@ #include "ini_parser.h" #include "vr_packet.h" #include "vr_message.h" +#include "vr_mem.h" #define TABLE_FLAG_VALID 0x1 @@ -1695,30 +1696,9 @@ flow_table_map(vr_flow_table_data *table) return ft->ft_num_entries; } - const char *platform = read_string(DEFAULT_SECTION, PLATFORM_KEY); - if (platform && ((strcmp(platform, PLATFORM_DPDK) == 0) || - (strcmp(platform, PLATFORM_NIC) == 0))) { - flow_path = table->ftable_file_path; - } else { - flow_path = MEM_DEV; - ret = mknod(MEM_DEV, S_IFCHR | O_RDWR, - makedev(table->ftable_dev, table->ftable_rid)); - if (ret && errno != EEXIST) { - perror(MEM_DEV); - exit(errno); - } - } - - mem_fd = open(flow_path, O_RDONLY | O_SYNC); - if (mem_fd <= 0) { - perror(MEM_DEV); - exit(errno); - } - - ft->ft_entries = (struct vr_flow_entry *)mmap(NULL, table->ftable_size, - PROT_READ, MAP_SHARED, mem_fd, 0); - /* the file descriptor is no longer needed */ - close(mem_fd); + ft->ft_entries = (struct vr_flow_entry *)vr_table_map(table->ftable_dev, + VR_MEM_FLOW_TABLE_OBJECT, table->ftable_file_path, + table->ftable_size); if (ft->ft_entries == MAP_FAILED) { printf("flow table: %s\n", strerror(errno)); exit(errno); diff --git a/utils/nl_util.c b/utils/nl_util.c index 6f201444e..19a4b3c1e 100644 --- a/utils/nl_util.c +++ b/utils/nl_util.c @@ -53,6 +53,9 @@ extern void vr_mem_stats_req_process(void *s_req) __attribute__((weak)); extern void vr_fc_map_req_process(void *s_req) __attribute__((weak)); extern void vr_qos_map_req_process(void *s_req) __attribute__((weak)); extern void vr_flow_table_data_process(void *s_req) __attribute__((weak)); +#if 0 +extern void vr_bridge_table_data_process(void *s_req) __attribute__((weak)); +#endif void vrouter_ops_process(void *s_req) @@ -158,6 +161,14 @@ vr_fc_map_req_process(void *s_req) return; } +#if 0 +void +vr_bridge_table_data_process(void *s_req) +{ + return; +} +#endif + struct nl_response * nl_parse_gen_ctrl(struct nl_client *cl) { diff --git a/utils/rt.c b/utils/rt.c index 1e3cd7e6a..50edf9602 100644 --- a/utils/rt.c +++ b/utils/rt.c @@ -13,9 +13,11 @@ #include #include #include +#include #include #include +#include #include @@ -34,6 +36,9 @@ #include "vr_route.h" #include "vr_bridge.h" #include "vr_os.h" +#include "ini_parser.h" +#include "vr_mem.h" +#include "vrouter.h" static struct nl_client *cl; static int resp_code; @@ -69,6 +74,15 @@ static void usage_internal(void); #define INET_FAMILY_STRING "inet" #define BRIDGE_FAMILY_STRING "bridge" #define INET6_FAMILY_STRING "inet6" +#define BRIDGE_TABLE_DEV "/dev/vr_bridge" + +static int mem_fd = -1; +static struct bridge_table { + unsigned int bt_size; + unsigned int bt_num_entries; + struct vr_bridge_entry *bt_entries; +} vr_bridge_table; + struct vr_util_flags inet_flags[] = { {VR_RT_LABEL_VALID_FLAG, "L", "Label Valid" }, @@ -129,6 +143,49 @@ family_string_to_id(char *fname) return -1; } +static void +vr_bridge_print_route(uint8_t *mac, unsigned int index, + unsigned int flags, unsigned int label, + unsigned int nh_id, uint64_t packets) +{ + int ret, i; + char flag_string[32]; + + bzero(flag_string, sizeof(flag_string)); + if (flags & VR_BE_LABEL_VALID_FLAG) + strcat(flag_string, "L"); + if (flags & VR_BE_FLOOD_DHCP_FLAG) + strcat(flag_string, "Df"); + + ret = printf("%-9d", index); + for (i = ret; i < 12; i++) + printf(" "); + + ret = printf("%s", ether_ntoa((struct ether_addr *)(mac))); + for (i = ret; i < 20; i++) + printf(" "); + + ret = printf(" %9s", flag_string); + + for (i = 0; i < 11; i++) + printf(" "); + + if (flags & VR_BE_LABEL_VALID_FLAG) + ret = printf(" %9d", label); + else + ret = printf(" %9c", '-'); + + for (i = 0; i < 6; i++) + printf(" "); + printf("%7d", nh_id); + + for (i = 0; i < 4; i++) + printf(" "); + printf("%12lu\n", packets); + + return; +} + void vr_route_req_process(void *s_req) { @@ -193,34 +250,8 @@ vr_route_req_process(void *s_req) printf("\n"); } else { memcpy(rt_marker, rt->rtr_mac, VR_ETHER_ALEN); - - bzero(flags, sizeof(flags)); - if (rt->rtr_label_flags & VR_BE_LABEL_VALID_FLAG) - strcat(flags, "L"); - if (rt->rtr_label_flags & VR_BE_FLOOD_DHCP_FLAG) - strcat(flags, "Df"); - - ret = printf("%-9d", rt->rtr_index); - for (i = ret; i < 12; i++) - printf(" "); - - ret = printf("%s", ether_ntoa((struct ether_addr *)(rt->rtr_mac))); - for (i = ret; i < 20; i++) - printf(" "); - - ret = printf(" %8s", flags); - for (i = ret; i < 10; i++) - printf(" "); - - if (rt->rtr_label_flags & VR_BE_LABEL_VALID_FLAG) - ret = printf(" %16d", rt->rtr_label); - else - ret = printf(" %16c", '-'); - - for (i = ret; i < 20; i++) - printf(" "); - - printf(" %10d\n", rt->rtr_nh_id); + vr_bridge_print_route(rt->rtr_mac, rt->rtr_index, + rt->rtr_label_flags, rt->rtr_label, rt->rtr_nh_id, 0); } return; @@ -253,7 +284,7 @@ vr_print_rtable_header(unsigned int family, unsigned int vrf) case AF_BRIDGE: printf("vRouter bridge table %d/%d\n", 0, cmd_vrf_id); printf("Index DestMac Flags " - "Label/VNID Nexthop\n"); + "Label/VNID Nexthop Stats\n"); break; default: @@ -263,6 +294,26 @@ vr_print_rtable_header(unsigned int family, unsigned int vrf) return; } +#if 0 +static void +vr_bridge_table_dump(unsigned int vrf) +{ + unsigned int i; + struct vr_bridge_entry *be; + + for (i = 0; i < vr_bridge_table.bt_num_entries; i++) { + be = &vr_bridge_table.bt_entries[i]; + if (!(be->be_flags & VR_BE_VALID_FLAG) || + (be->be_key.be_vrf_id != vrf)) + continue; + vr_bridge_print_route(be->be_key.be_mac, i, be->be_flags, + be->be_label, be->be_nh_id, be->be_packets); + } + + return; +} +#endif + static int vr_route_op(struct nl_client *cl) { @@ -297,9 +348,19 @@ vr_route_op(struct nl_client *cl) break; case SANDESH_OP_DUMP: - dump = true; - ret = vr_send_route_dump(cl, 0, cmd_vrf_id, cmd_family_id, +#if 0 + if (cmd_family_id == AF_BRIDGE) { + vr_bridge_table_dump(cmd_vrf_id); + return 0; + } else { +#endif + dump = true; + ret = vr_send_route_dump(cl, 0, cmd_vrf_id, cmd_family_id, rt_marker); +#if 0 + } +#endif + break; case SANDESH_OP_DELETE: @@ -332,6 +393,52 @@ vr_route_op(struct nl_client *cl) return 0; } +#if 0 +static int +bridge_table_map(vr_bridge_table_data *table) +{ + vr_bridge_table.bt_size = table->btable_size; + vr_bridge_table.bt_num_entries = + table->btable_size / sizeof(struct vr_bridge_entry); + + vr_bridge_table.bt_entries = + vr_table_map(table->btable_dev, VR_MEM_BRIDGE_TABLE_OBJECT, + table->btable_file_path, table->btable_size); + if (vr_bridge_table.bt_entries == MAP_FAILED) { + printf("bridge table: %s\n", strerror(errno)); + exit(errno); + } + + return 0; +} + +void +vr_bridge_table_data_process(void *s_req) +{ + vr_bridge_table_data *req = (vr_bridge_table_data *)s_req; + + bridge_table_map(req); + + return; +} + +static int +vr_bridge_table_setup(struct nl_client *cl) +{ + int ret; + + ret = vr_send_get_bridge_table_data(cl); + if (!ret) + return ret; + + ret = vr_recvmsg(cl, false); + if (ret <= 0) + return -1; + + return 0; +} +#endif + static void usage_internal() { @@ -693,6 +800,17 @@ main(int argc, char *argv[]) exit(1); } +#if 0 + if (cmd_family_id == AF_BRIDGE) { + if (cmd_op == SANDESH_OP_DUMP || cmd_op == SANDESH_OP_GET) { + ret = vr_bridge_table_setup(cl); + if (ret) { + exit(1); + } + } + } +#endif + vr_route_op(cl); return 0; } diff --git a/utils/vr_util.c b/utils/vr_util.c index ef8a55e03..5efa2f355 100644 --- a/utils/vr_util.c +++ b/utils/vr_util.c @@ -14,8 +14,12 @@ #include #include #include +#include +#include +#include #include +#include #if defined(__linux__) #include #include @@ -37,6 +41,7 @@ #include "vr_nexthop.h" #include "vr_route.h" #include "vr_bridge.h" +#include "vr_mem.h" #include "ini_parser.h" /* Suppress NetLink error messages */ @@ -311,6 +316,71 @@ vr_get_nl_client(int proto) return NULL; } +void * +vr_table_map(int major, unsigned int table, + char *table_path, size_t size) +{ + int fd, ret; + uint16_t dev; + + void *mem; + char *path; + const char *platform = read_string(DEFAULT_SECTION, PLATFORM_KEY); + + if (major < 0) + return NULL; + + if (platform && ((strcmp(platform, PLATFORM_DPDK) == 0) || + (strcmp(platform, PLATFORM_NIC) == 0))) { + path = table_path; + } else { + switch (table) { + case VR_MEM_BRIDGE_TABLE_OBJECT: + path = BRIDGE_TABLE_DEV; + break; + + case VR_MEM_FLOW_TABLE_OBJECT: + path = FLOW_TABLE_DEV; + break; + + default: + return NULL; + } + + ret = mknod(path, S_IFCHR | O_RDWR, makedev(major, table)); + if (ret && errno != EEXIST) { + perror(path); + return NULL; + } + } + + fd = open(path, O_RDONLY | O_SYNC); + if (fd <= 0) { + perror(path); + return NULL; + } + + mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + + return mem; +} + +#if 0 +int +vr_send_get_bridge_table_data(struct nl_client *cl) +{ + int ret; + vr_bridge_table_data req; + + memset(&req, 0, sizeof(req)); + req.btable_op = SANDESH_OP_GET; + req.btable_rid = 0; + + return vr_sendmsg(cl, &req, "vr_bridge_table_data"); +} +#endif + int vr_send_set_dcb_state(struct nl_client *cl, uint8_t *ifname, uint8_t state) { diff --git a/utils/vtest/sandesh_gen.c b/utils/vtest/sandesh_gen.c index dc22a30dd..bfab3ff2b 100644 --- a/utils/vtest/sandesh_gen.c +++ b/utils/vtest/sandesh_gen.c @@ -498,7 +498,7 @@ gen(FILE *fp) gen_write(fp_expect, 0, "_size"); gen_write(fp_expect, 0, ", node->children->content, GEN_TYPE_U8);\n"); - } else if (!strncmp(sub_type, "i16", strlen("i32"))) { + } else if (!strncmp(sub_type, "i16", strlen("i16"))) { gen_write(ofp, 0, "vt_gen_list(node->children->content, GEN_TYPE_U16, &list_size);\n"); gen_write(fp_expect, 0, "result = vt_gen_list_compare("); @@ -510,7 +510,8 @@ gen(FILE *fp) gen_write(fp_expect, 0, "_size"); gen_write(fp_expect, 0, ", node->children->content, GEN_TYPE_U16);\n"); - } else if (!strncmp(sub_type, "i32", strlen("i32"))) { + } else if (!strncmp(sub_type, "i32", strlen("i32")) || + !strncmp(sub_type, "u32", strlen("u32"))) { gen_write(ofp, 0, "vt_gen_list(node->children->content, GEN_TYPE_U32, &list_size);\n"); gen_write(fp_expect, 0, "result = vt_gen_list_compare("); @@ -522,7 +523,7 @@ gen(FILE *fp) gen_write(fp_expect, 0, "_size"); gen_write(fp_expect, 0, ", node->children->content, GEN_TYPE_U32);\n"); - } else if (!strncmp(sub_type, "i64", strlen("i32"))) { + } else if (!strncmp(sub_type, "i64", strlen("i64"))) { gen_write(ofp, 0, "vt_gen_list(node->children->content, GEN_TYPE_U64, &list_size);\n"); gen_write(fp_expect, 0, "result = vt_gen_list_compare(");