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(");