switch_status_t switch_api_nhop_print_entry(switch_handle_t nhop_handle) { switch_nhop_info_t *nhop_info = NULL; switch_spath_info_t *spath_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; switch_ecmp_member_t *ecmp_member = NULL; tommy_node *node = NULL; nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } printf("\n\nnhop_handle %x", (unsigned int) nhop_handle); if (nhop_info->type == SWITCH_NHOP_INDEX_TYPE_ONE_PATH) { spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); printf("\ntype : single path"); printf("\nintf_handle %x", (unsigned int) spath_info->nhop_key.intf_handle); } else { ecmp_info = &(SWITCH_NHOP_ECMP_INFO(nhop_info)); printf("\ntype : ecmp path"); printf("\nnumber of ecmp path %d", ecmp_info->count); node = tommy_list_head(&(ecmp_info->members)); while (node) { ecmp_member = node->data; printf("\n\tecmp_member_nhop %x", (unsigned int) ecmp_member->nhop_handle); node = node->next; } } return SWITCH_STATUS_SUCCESS; }
switch_handle_t switch_api_ecmp_create(switch_device_t device) { switch_handle_t nhop_handle; switch_nhop_info_t *nhop_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; nhop_handle = switch_nhop_create(); nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } nhop_info->type = SWITCH_NHOP_INDEX_TYPE_ECMP; ecmp_info = &(SWITCH_NHOP_ECMP_INFO(nhop_info)); memset(ecmp_info, 0, sizeof(switch_ecmp_info_t)); ecmp_info->hw_entry = SWITCH_HW_INVALID_HANDLE; ecmp_info->count = 0; tommy_list_init(&(ecmp_info->members)); #ifdef SWITCH_PD status = switch_pd_ecmp_group_create(device, &(ecmp_info->pd_group_hdl)); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } #endif return nhop_handle; }
switch_status_t switch_api_l3_route_lookup(switch_device_t device, switch_handle_t vrf, switch_ip_addr_t *ip_addr, switch_handle_t *nhop_handle) { switch_l3_hash_t *hash_entry = NULL; switch_nhop_info_t *nhop_info = NULL; if (switch_l3_host_entry(ip_addr)) { // host entry, first search hash hash_entry = switch_l3_search_hash(vrf, ip_addr); } if (!hash_entry) { // try LPM lookup hash_entry = switch_l3_lookup_lpm_trie(vrf, ip_addr); } if (!hash_entry) { *nhop_handle = SWITCH_API_INVALID_HANDLE; return SWITCH_STATUS_ITEM_NOT_FOUND; } nhop_info = switch_nhop_get(hash_entry->nhop_handle); if (!nhop_info) { SWITCH_API_ERROR("%s:%d: Invalid nexthop!", __FUNCTION__, __LINE__); *nhop_handle = SWITCH_API_INVALID_HANDLE; return SWITCH_STATUS_ITEM_NOT_FOUND; } *nhop_handle = hash_entry->nhop_handle; return SWITCH_STATUS_SUCCESS; }
switch_handle_t switch_api_neighbor_entry_add(switch_device_t device, switch_api_neighbor_t *neighbor) { switch_neighbor_info_t *neighbor_info = NULL; switch_interface_info_t *intf_info = NULL; switch_handle_t handle = SWITCH_API_INVALID_HANDLE; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_nhop_info_t *nhop_info = NULL; switch_spath_info_t *spath_info = NULL; switch_handle_t nhop_handle = 0; intf_info = switch_api_interface_get(neighbor->interface); if (!intf_info) { SWITCH_API_ERROR( "%s:%d: invalid interface for rewrite!", __FUNCTION__, __LINE__); return SWITCH_STATUS_INVALID_INTERFACE; } handle = switch_neighbor_info_create(); neighbor_info = switch_neighbor_info_get(handle); memcpy(&neighbor_info->neighbor, neighbor, sizeof(switch_api_neighbor_t)); #ifdef SWITCH_PD nhop_handle = neighbor->nhop_handle; if (neighbor->nhop_handle == SWITCH_API_INVALID_HANDLE) { // check for neighbor type if (neighbor->neigh_type == SWITCH_API_NEIGHBOR_NONE && neighbor->rw_type == SWITCH_API_NEIGHBOR_RW_TYPE_L3) { switch_nhop_key_t nhop_key; // allocate nhop and set neighbor handle memset(&nhop_key, 0, sizeof(nhop_key)); nhop_key.ip_addr = neighbor->ip_addr; nhop_key.intf_handle = neighbor->interface; nhop_key.ip_addr_valid = 1; nhop_handle = switch_api_nhop_create(device, &nhop_key); } } if (nhop_handle != SWITCH_API_INVALID_HANDLE && nhop_handle) { nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); spath_info->neighbor_handle = handle; neighbor_info->neighbor.nhop_handle = nhop_handle; status = switch_api_nhop_update(device, nhop_handle); status = switch_api_neighbor_entry_add_rewrite(device, handle, neighbor_info); } else { status = switch_api_neighbor_entry_add_tunnel_rewrite(device, neighbor_info); } #endif if (status != SWITCH_STATUS_SUCCESS) { SWITCH_API_ERROR( "%s:%d: failed to create neighbor entry!", __FUNCTION__, __LINE__); } neighbor->nhop_handle = nhop_handle; return handle; }
switch_status_t switch_api_neighbor_entry_remove( switch_device_t device, switch_handle_t neighbor_handle) { switch_neighbor_info_t *neighbor_info = NULL; switch_api_neighbor_t *neighbor = NULL; switch_nhop_info_t *nhop_info = NULL; switch_interface_info_t *intf_info = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_NEIGHBOR_HANDLE_VALID(neighbor_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } neighbor_info = switch_neighbor_info_get(neighbor_handle); if (!neighbor_info) { return SWITCH_STATUS_ITEM_NOT_FOUND; } #ifdef SWITCH_PD if (neighbor_info->neighbor.nhop_handle) { status = switch_pd_rewrite_table_delete_entry(device, neighbor_info->rewrite_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } neighbor = &neighbor_info->neighbor; intf_info = switch_api_interface_get(neighbor->interface); if (!intf_info) { SWITCH_API_ERROR("%s:%d invalid interface!", __FUNCTION__, __LINE__); return SWITCH_STATUS_INVALID_INTERFACE; } switch_neighbor_dmac_delete_hash( device, intf_info->bd_handle, &neighbor->mac_addr); } else { status = switch_dmac_rewrite_delete_hash(device, &neighbor_info->neighbor.mac_addr); if (status != SWITCH_STATUS_SUCCESS) { return status; } status = switch_pd_tunnel_rewrite_table_delete_entry( device, neighbor_info->rewrite_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } } #endif switch_neighbor_info_delete(neighbor_handle); nhop_info = switch_nhop_get(neighbor_info->neighbor.nhop_handle); if (nhop_info) { nhop_info->u.spath.neighbor_handle = 0; status = switch_api_nhop_update(device, neighbor_info->neighbor.nhop_handle); if (nhop_info->valid == 0) { switch_api_nhop_delete(device, neighbor_info->neighbor.nhop_handle); } } return status; }
switch_status_t switch_api_ecmp_delete(switch_device_t device, switch_handle_t handle) { switch_nhop_info_t *nhop_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; tommy_node *node = NULL; switch_ecmp_member_t *ecmp_member = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_NHOP_HANDLE_VALID(handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_info = switch_nhop_get(handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } if (nhop_info->type != SWITCH_NHOP_INDEX_TYPE_ONE_PATH) { ecmp_info = &(SWITCH_NHOP_ECMP_INFO(nhop_info)); if (ecmp_info->count > 0) { node = tommy_list_head(&(ecmp_info->members)); while (node) { ecmp_member = (switch_ecmp_member_t *) node->data; nhop_info = switch_nhop_get(ecmp_member->nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } nhop_info->ref_count--; node = node->next; } } #ifdef SWITCH_PD status = switch_pd_ecmp_group_delete(device, ecmp_info->pd_group_hdl); if (status != SWITCH_STATUS_SUCCESS) { return status; } #endif } return switch_nhop_delete(handle); }
switch_status_t switch_api_nhop_delete(switch_device_t device, switch_handle_t nhop_handle) { switch_nhop_info_t *nhop_info = NULL; switch_interface_info_t *intf_info = NULL; switch_spath_info_t *spath_info = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_HANDLE; } if (nhop_info->type != SWITCH_NHOP_INDEX_TYPE_ONE_PATH) { return SWITCH_STATUS_INVALID_HANDLE; } if (nhop_info->ref_count) { return SWITCH_STATUS_RESOURCE_IN_USE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_INTERFACE; } nhop_info->valid = 0; if(nhop_info->u.spath.neighbor_handle == 0) { #ifdef SWITCH_PD status = switch_pd_nexthop_table_delete_entry(device, spath_info->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } if (SWITCH_INTF_IS_PORT_L3(intf_info) && intf_info->bd_handle) { status = switch_pd_urpf_bd_table_delete_entry(device, spath_info->urpf_hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } } #endif switch_nhop_delete_hash(spath_info); switch_nhop_delete(nhop_handle); } return SWITCH_STATUS_SUCCESS; }
switch_nhop_index_type_t switch_api_nhop_type_get(switch_handle_t nhop_handle) { switch_nhop_info_t *nhop_info = NULL; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_NHOP_INDEX_TYPE_NONE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_NHOP_INDEX_TYPE_NONE; } return nhop_info->type; }
switch_status_t switch_api_nhop_get(switch_device_t device, switch_handle_t handle, switch_nhop_key_t **nhop_key) { switch_nhop_info_t *info = switch_nhop_get(handle); switch (info->type) { case SWITCH_NHOP_INDEX_TYPE_ONE_PATH: *nhop_key = &info->u.spath.nhop_key; break; case SWITCH_NHOP_INDEX_TYPE_ECMP: case SWITCH_NHOP_INDEX_TYPE_NONE: return SWITCH_STATUS_NOT_SUPPORTED; } return SWITCH_STATUS_SUCCESS; }
switch_status_t switch_api_nhop_set(switch_device_t device, switch_handle_t handle, switch_nhop_key_t *nhop_key) { switch_nhop_info_t *info = switch_nhop_get(handle); switch (info->type) { case SWITCH_NHOP_INDEX_TYPE_ONE_PATH: // need to check each field in key diff? memcpy(&info->u.spath.nhop_key, nhop_key, sizeof(switch_nhop_key_t)); break; case SWITCH_NHOP_INDEX_TYPE_ECMP: case SWITCH_NHOP_INDEX_TYPE_NONE: return SWITCH_STATUS_NOT_SUPPORTED; } return switch_api_nhop_update(device, handle); }
switch_handle_t switch_api_neighbor_handle_get(switch_handle_t nhop_handle) { switch_nhop_info_t *nhop_info = NULL; switch_spath_info_t *spath_info = NULL; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_API_INVALID_HANDLE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); return spath_info->neighbor_handle; }
switch_status_t switch_api_nhop_update(switch_device_t device, switch_handle_t nhop_handle) { switch_nhop_info_t *nhop_info = NULL; switch_interface_info_t *intf_info = NULL; switch_spath_info_t *spath_info = NULL; switch_ifindex_t ifindex = 0; bool flood = FALSE; uint32_t mc_index = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_HANDLE; } status = switch_nhop_ifindex_get(nhop_handle, &ifindex, &flood, &mc_index); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_INVALID_HANDLE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_INTERFACE; } #ifdef SWITCH_PD bool tunnel = (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_TUNNEL); status = switch_pd_nexthop_table_update_entry(device, handle_to_id(nhop_handle), handle_to_id(intf_info->bd_handle), ifindex, flood, mc_index, tunnel, &spath_info->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } #endif return SWITCH_STATUS_SUCCESS; }
switch_status_t switch_api_l3_route_nhop_intf_get( switch_device_t device, switch_handle_t vrf, switch_ip_addr_t *ip_addr, switch_handle_t *intf_handle) { switch_nhop_info_t *nhop_info = NULL; switch_spath_info_t *spath_info = NULL; switch_interface_info_t *intf_info = NULL; switch_handle_t nhop_handle = SWITCH_API_INVALID_HANDLE; switch_status_t status; *intf_handle = SWITCH_API_INVALID_HANDLE; status = switch_api_l3_route_lookup(device, vrf, ip_addr, &nhop_handle); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_ITEM_NOT_FOUND; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_ITEM_NOT_FOUND; } if (nhop_info->type != SWITCH_NHOP_INDEX_TYPE_ONE_PATH) { return SWITCH_STATUS_ITEM_NOT_FOUND; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); if (!spath_info) { return SWITCH_STATUS_ITEM_NOT_FOUND; } // additional check if intf_handle is valid intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_ITEM_NOT_FOUND; } *intf_handle = spath_info->nhop_key.intf_handle; return SWITCH_STATUS_SUCCESS; }
switch_status_t switch_api_l3_route_add(switch_device_t device, switch_handle_t vrf, switch_ip_addr_t *ip_addr, switch_handle_t nhop_handle) { switch_l3_hash_t *hash_entry = NULL; switch_nhop_info_t *nhop_info = NULL; uint32_t nhop_index = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; unsigned int v4_mask = 0; uint8_t v6_mask[16]; switch_ip_addr_t masked_ip; if (!SWITCH_VRF_HANDLE_VALID(vrf)) { return SWITCH_STATUS_INVALID_HANDLE; } if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_index = handle_to_id(nhop_handle); nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { SWITCH_API_ERROR("%s:%d: Invalid nexthop!", __FUNCTION__, __LINE__); return SWITCH_STATUS_ITEM_NOT_FOUND; } hash_entry = switch_l3_search_hash(vrf, ip_addr); if (hash_entry) { hash_entry->nhop_handle = nhop_handle; #ifdef SWITCH_PD status = switch_pd_ip_fib_update_entry(device, handle_to_id(vrf), ip_addr, SWITCH_NHOP_TYPE_IS_ECMP(nhop_info), nhop_index, hash_entry->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } status = switch_pd_urpf_update_entry(device, handle_to_id(vrf), ip_addr, handle_to_id(nhop_handle), hash_entry->urpf_entry); #endif } else { memcpy(&masked_ip, ip_addr, sizeof(switch_ip_addr_t)); if (ip_addr->type == SWITCH_API_IP_ADDR_V4) { v4_mask = prefix_to_v4_mask(ip_addr->prefix_len); masked_ip.ip.v4addr = ip_addr->ip.v4addr & v4_mask; } else { int i = 0; prefix_to_v6_mask(ip_addr->prefix_len, v6_mask); for (i = 0; i < 16; i++) { masked_ip.ip.v6addr[i] = ip_addr->ip.v6addr[i] & v6_mask[i]; } } hash_entry = switch_l3_insert_hash(vrf, ip_addr, nhop_handle); if (!hash_entry) { return SWITCH_STATUS_NO_MEMORY; } hash_entry->nhop_handle = nhop_handle; #ifdef SWITCH_PD // set the HW entry status = switch_pd_ip_fib_add_entry(device, handle_to_id(vrf), ip_addr, SWITCH_NHOP_TYPE_IS_ECMP(nhop_info), nhop_index, &hash_entry->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } status = switch_pd_urpf_add_entry(device, handle_to_id(vrf), ip_addr, handle_to_id(nhop_handle), &hash_entry->urpf_entry); #endif } return status; }
switch_handle_t switch_api_nhop_create(switch_device_t device, switch_nhop_key_t *nhop_key) { switch_handle_t nhop_handle; switch_nhop_info_t *nhop_info = NULL; switch_interface_info_t *intf_info = NULL; switch_spath_info_t *spath_info = NULL; switch_ifindex_t ifindex = 0; bool flood = FALSE; uint32_t mc_index = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_INTERFACE_HANDLE_VALID(nhop_key->intf_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } intf_info = switch_api_interface_get(nhop_key->intf_handle); if (!intf_info) { return SWITCH_API_INVALID_HANDLE; } if((nhop_handle = switch_api_nhop_handle_get(nhop_key)) == SWITCH_API_INVALID_HANDLE) { nhop_handle = switch_nhop_create(); } else { nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } return nhop_handle; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } nhop_info->type = SWITCH_NHOP_INDEX_TYPE_ONE_PATH; spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); spath_info->nhop_key.intf_handle = nhop_key->intf_handle; intf_info->nhop_handle = nhop_handle; nhop_info->valid = 1; status = switch_nhop_ifindex_get(nhop_handle, &ifindex, &flood, &mc_index); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } #ifdef SWITCH_PD bool tunnel = (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_TUNNEL); status = switch_pd_nexthop_table_add_entry(device, handle_to_id(nhop_handle), handle_to_id(intf_info->bd_handle), ifindex, flood, mc_index, tunnel, &spath_info->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } if (SWITCH_INTF_IS_PORT_L3(intf_info) && intf_info->bd_handle) { status = switch_pd_urpf_bd_table_add_entry(device, handle_to_id(nhop_handle), handle_to_id(intf_info->bd_handle), &spath_info->urpf_hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } } #endif if (nhop_key->ip_addr_valid) { switch_nhop_insert_hash(spath_info, nhop_key, nhop_handle); } return nhop_handle; }
switch_handle_t switch_api_ecmp_create_with_members(switch_device_t device, uint32_t member_count, switch_handle_t *nhop_handle) { switch_nhop_info_t *nhop_info = NULL; switch_spath_info_t *spath_info = NULL; switch_interface_info_t *intf_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; switch_ecmp_member_t *ecmp_member = NULL; switch_handle_t ecmp_handle; switch_status_t status = SWITCH_STATUS_SUCCESS; uint32_t index = 0; ecmp_handle = switch_api_ecmp_create(device); nhop_info = switch_nhop_get(ecmp_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } ecmp_info = &(SWITCH_NHOP_ECMP_INFO(nhop_info)); tommy_list_init(&ecmp_info->members); #ifdef SWITCH_PD status = switch_pd_ecmp_group_create(device, &(ecmp_info->pd_group_hdl)); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } #endif for (index = 0; index < member_count; index++) { if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle[index])) { return SWITCH_STATUS_INVALID_HANDLE; } ecmp_member = switch_malloc(sizeof(switch_ecmp_member_t), 1); if (!ecmp_member) { // TODO: Cleanup memory return SWITCH_API_INVALID_HANDLE; } ecmp_member->nhop_handle = nhop_handle[index]; ecmp_member->mbr_hdl = 0; nhop_info = switch_nhop_get(ecmp_member->nhop_handle); if (!nhop_info) { return SWITCH_API_INVALID_HANDLE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_API_INVALID_HANDLE; } nhop_info->ref_count++; #ifdef SWITCH_PD status = switch_pd_ecmp_member_add(device, ecmp_info->pd_group_hdl, handle_to_id(ecmp_member->nhop_handle), intf_info, &(ecmp_member->mbr_hdl)); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } if (SWITCH_INTF_IS_PORT_L3(intf_info) && intf_info->bd_handle) { status = switch_pd_urpf_bd_table_add_entry(device, handle_to_id(ecmp_handle), handle_to_id(intf_info->bd_handle), &(ecmp_member->urpf_hw_entry)); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } } #endif tommy_list_insert_head(&ecmp_info->members, &(ecmp_member->node), ecmp_member); } #ifdef SWITCH_PD status = switch_pd_ecmp_group_table_add_entry_with_selector(device, handle_to_id(ecmp_handle), ecmp_info->pd_group_hdl, &(ecmp_info->hw_entry)); if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } #endif ecmp_info->count = member_count; if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_API_INVALID_HANDLE; } return ecmp_handle; }
switch_status_t switch_api_ecmp_member_add(switch_device_t device, switch_handle_t ecmp_handle, uint16_t nhop_count, switch_handle_t *nhop_handle_list) { switch_nhop_info_t *e_nhop_info = NULL; switch_nhop_info_t *nhop_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; switch_ecmp_member_t *ecmp_member = NULL; switch_interface_info_t *intf_info = NULL; switch_spath_info_t *spath_info = NULL; switch_handle_t nhop_handle; switch_status_t status = SWITCH_STATUS_SUCCESS; int count = 0; if (!SWITCH_NHOP_HANDLE_VALID(ecmp_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } e_nhop_info = switch_nhop_get(ecmp_handle); if (!e_nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } ecmp_info = &(SWITCH_NHOP_ECMP_INFO(e_nhop_info)); for (count = 0; count < nhop_count; count++) { nhop_handle = nhop_handle_list[count]; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); ecmp_member = switch_malloc(sizeof(switch_ecmp_member_t), 1); if (!ecmp_member) { return SWITCH_STATUS_NO_MEMORY; } ecmp_member->nhop_handle = nhop_handle; intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_INTERFACE; } nhop_info->ref_count++; #ifdef SWITCH_PD status = switch_pd_ecmp_member_add(device, ecmp_info->pd_group_hdl, handle_to_id(ecmp_member->nhop_handle), intf_info, &(ecmp_member->mbr_hdl)); if (status != SWITCH_STATUS_SUCCESS) { return status; } if (ecmp_info->count == 0) { status = switch_pd_ecmp_group_table_add_entry_with_selector(device, handle_to_id(ecmp_handle), ecmp_info->pd_group_hdl, &(ecmp_info->hw_entry)); if (status != SWITCH_STATUS_SUCCESS) { return status; } } if (SWITCH_INTF_IS_PORT_L3(intf_info) && intf_info->bd_handle) { status = switch_pd_urpf_bd_table_add_entry(device, handle_to_id(ecmp_handle), handle_to_id(intf_info->bd_handle), &(ecmp_member->urpf_hw_entry)); if (status != SWITCH_STATUS_SUCCESS) { return status; } } #endif ecmp_info->count++; tommy_list_insert_head(&ecmp_info->members, &(ecmp_member->node), ecmp_member); } return status; }
switch_status_t switch_nhop_ifindex_get(switch_handle_t nhop_handle, switch_ifindex_t *ifindex, bool *flood, uint32_t *mc_index) { switch_nhop_info_t *nhop_info = NULL; switch_interface_info_t *intf_info = NULL; switch_neighbor_info_t *neighbor_info = NULL; switch_api_neighbor_t *neighbor = NULL; switch_api_mac_entry_t mac_entry; switch_mac_info_t *mac_info = NULL; switch_handle_t neighbor_handle; switch_bd_info_t *bd_info = NULL; switch_port_info_t *tmp_port_info = NULL; switch_lag_info_t *tmp_lag_info = NULL; switch_interface_info_t *tmp_intf_info = NULL; switch_api_mac_entry_t *tmp_mac_entry = NULL; switch_handle_type_t handle_type = 0; switch_handle_t encap_if; switch_spath_info_t *spath_info = NULL; nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_HANDLE; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_HANDLE; } *ifindex = intf_info->ifindex; *flood = FALSE; *mc_index = 0; if (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_TUNNEL) { encap_if = SWITCH_INTF_TUNNEL_ENCAP_OUT_IF(intf_info); intf_info = switch_api_interface_get(encap_if); if (!intf_info) { return SWITCH_STATUS_INVALID_HANDLE; } *ifindex = intf_info->ifindex; SWITCH_API_TRACE("%s:%d ifindex for tunnel interface: %x", __FUNCTION__, __LINE__, *ifindex); } if (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_L3_VLAN) { neighbor_handle = spath_info->neighbor_handle; if (neighbor_handle == SWITCH_API_INVALID_HANDLE || neighbor_handle == 0) { *ifindex = switch_api_cpu_glean_ifindex(); } else { neighbor_info = switch_neighbor_info_get(neighbor_handle); if (!neighbor_info) { return SWITCH_STATUS_INVALID_HANDLE; } neighbor = &neighbor_info->neighbor; memset(&mac_entry, 0, sizeof(switch_api_mac_entry_t)); mac_entry.vlan_handle = intf_info->bd_handle; memcpy(&mac_entry.mac, &neighbor->mac_addr, ETH_LEN); mac_info = switch_mac_table_entry_find(&mac_entry); if (!mac_info) { bd_info = switch_bd_get(intf_info->bd_handle); if (!bd_info) { return SWITCH_STATUS_INVALID_HANDLE; } *mc_index = handle_to_id(bd_info->uuc_mc_index); *flood = TRUE; } else { tmp_mac_entry = &mac_info->mac_entry; handle_type = switch_handle_get_type(tmp_mac_entry->handle); switch (handle_type) { case SWITCH_HANDLE_TYPE_PORT: tmp_port_info = switch_api_port_get_internal(tmp_mac_entry->handle); if (!tmp_port_info) { return SWITCH_STATUS_INVALID_HANDLE; } *ifindex = tmp_port_info->ifindex; break; case SWITCH_HANDLE_TYPE_LAG: tmp_lag_info = switch_api_lag_get_internal(tmp_mac_entry->handle); if (!tmp_lag_info) { return SWITCH_STATUS_INVALID_HANDLE; } *ifindex = tmp_lag_info->ifindex; break; case SWITCH_HANDLE_TYPE_INTERFACE: tmp_intf_info = switch_api_interface_get(tmp_mac_entry->handle); if (!tmp_intf_info) { return SWITCH_STATUS_INVALID_HANDLE; } *ifindex = tmp_intf_info->ifindex; break; default: return SWITCH_STATUS_INVALID_HANDLE; } } } } return SWITCH_STATUS_SUCCESS; }
switch_status_t switch_api_ecmp_member_delete(switch_device_t device, switch_handle_t ecmp_handle, uint16_t nhop_count, switch_handle_t *nhop_handle_list) { switch_nhop_info_t *nhop_info = NULL; switch_nhop_info_t *e_nhop_info = NULL; switch_spath_info_t *spath_info = NULL; switch_interface_info_t *intf_info = NULL; switch_ecmp_info_t *ecmp_info = NULL; switch_ecmp_member_t *ecmp_member = NULL; tommy_node *node = NULL; switch_handle_t nhop_handle; switch_status_t status = SWITCH_STATUS_SUCCESS; int count = 0; if (!SWITCH_NHOP_HANDLE_VALID(ecmp_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } e_nhop_info = switch_nhop_get(ecmp_handle); if (!e_nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } for (count = 0; count < nhop_count; count++) { nhop_handle = nhop_handle_list[count]; if (!SWITCH_NHOP_HANDLE_VALID(nhop_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } nhop_info = switch_nhop_get(nhop_handle); if (!nhop_info) { return SWITCH_STATUS_INVALID_NHOP; } spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info)); ecmp_info = &(SWITCH_NHOP_ECMP_INFO(e_nhop_info)); node = tommy_list_head(&(ecmp_info->members)); while (node) { ecmp_member = (switch_ecmp_member_t *) node->data; if (ecmp_member->nhop_handle == nhop_handle) { break; } node = node->next; } if (!node) { return SWITCH_STATUS_ITEM_NOT_FOUND; } intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_INTERFACE; } nhop_info->ref_count--; #if SWITCH_PD if (ecmp_info->count == 1) { status = switch_pd_ecmp_group_table_delete_entry(device, ecmp_info->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } } status = switch_pd_ecmp_member_delete(device, ecmp_info->pd_group_hdl, ecmp_member->mbr_hdl); if (status != SWITCH_STATUS_SUCCESS) { return status; } if (SWITCH_INTF_IS_PORT_L3(intf_info) && intf_info->bd_handle) { status = switch_pd_urpf_bd_table_delete_entry(device, ecmp_member->urpf_hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } } #endif ecmp_info->count--; ecmp_member = tommy_list_remove_existing(&(ecmp_info->members), node); switch_free(ecmp_member); } return status; }