/* * @function: switch_api_router_mac_add * Add Router mac to rmac group * @param device - Device to be programmed * @param rmac_handle - ID of the RMAC group * @param mac - Router mac address to be added to the group * @return: Returns success if mac is added successfully */ switch_status_t switch_api_router_mac_add(switch_device_t device, switch_handle_t rmac_handle, switch_mac_addr_t *mac) { switch_rmac_info_t *rmac_info = NULL; switch_rmac_entry_t *rmac_entry = NULL; tommy_node *node = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!SWITCH_RMAC_HANDLE_VALID(rmac_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } rmac_info = switch_api_rmac_info_get_internal(rmac_handle); if (!rmac_info) { return SWITCH_STATUS_INVALID_HANDLE; } node = tommy_list_head(&(rmac_info->rmac_list)); while (node) { rmac_entry = node->data; if (memcmp(&(rmac_entry->mac), mac, sizeof(switch_mac_addr_t)) == 0) { return SWITCH_STATUS_SUCCESS; } node = node->next; } rmac_entry = switch_malloc(sizeof(switch_rmac_entry_t), 1); if (!rmac_entry) { return SWITCH_STATUS_NO_MEMORY; } memcpy(&rmac_entry->mac, mac, sizeof(switch_mac_addr_t)); tommy_list_insert_head(&(rmac_info->rmac_list), &(rmac_entry->node), rmac_entry); status = switch_smac_rewrite_add_entry(mac); if (status != SWITCH_STATUS_SUCCESS) { printf("MAC rewrite table add failed with error code %d\n", status); return status; } #ifdef SWITCH_PD status = switch_pd_inner_rmac_table_add_entry(device, handle_to_id(rmac_handle), mac, &rmac_entry->inner_rmac_entry); if(status != SWITCH_STATUS_SUCCESS) { printf("Inner RMAC table add failed with error code %d\n", status); return status; } status = switch_pd_outer_rmac_table_add_entry(device, handle_to_id(rmac_handle), mac, &rmac_entry->outer_rmac_entry); if(status != SWITCH_STATUS_SUCCESS) { printf("Outer RMAC table add failed with error code %d\n", status); } #endif return status; }
switch_status_t switch_api_l3_route_delete(switch_device_t device, switch_handle_t vrf, switch_ip_addr_t *ip_addr, switch_handle_t nhop_handle) { switch_status_t status = SWITCH_STATUS_SUCCESS; switch_l3_hash_t *hash_entry = NULL; if (!SWITCH_VRF_HANDLE_VALID(vrf)) { return SWITCH_STATUS_INVALID_HANDLE; } UNUSED(nhop_handle); hash_entry = switch_l3_search_hash(vrf, ip_addr); if (!hash_entry) { return SWITCH_STATUS_ITEM_NOT_FOUND; } #ifdef SWITCH_PD status = switch_pd_ip_fib_delete_entry(device, ip_addr, hash_entry->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } status = switch_pd_urpf_delete_entry( device, handle_to_id(vrf), ip_addr, hash_entry->urpf_entry); if (status != SWITCH_STATUS_SUCCESS) { return status; } #endif status = switch_l3_delete_hash(vrf, ip_addr); return status; }
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_stp_group_vlans_remove(switch_device_t device, switch_handle_t stg_handle, uint16_t vlan_count, switch_handle_t *vlan_handle) { switch_stp_info_t *stp_info = NULL; switch_bd_info_t *bd_info = NULL; switch_stp_vlan_entry_t *vlan_entry = NULL; tommy_node *node = NULL; switch_handle_t bd_handle; int count = 0; if (!SWITCH_STP_HANDLE_VALID(stg_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } stp_info = switch_api_stp_get_internal(stg_handle); if (!stp_info) { return SWITCH_STATUS_INVALID_HANDLE; } for (count = 0; count < vlan_count; count++) { bd_handle = vlan_handle[count]; bd_info = switch_bd_get(bd_handle); if (!bd_info) { return SWITCH_STATUS_INVALID_VLAN_ID; } node = tommy_list_head(&(stp_info->vlan_list)); while (node) { vlan_entry = node->data; if (vlan_entry->bd_handle == bd_handle) { break; } node = node->next; } if (!node) { return SWITCH_STATUS_ITEM_NOT_FOUND; } bd_info->stp_handle = 0; switch_pd_bd_table_update_entry(device, handle_to_id(bd_handle), bd_info); vlan_entry = tommy_list_remove_existing(&(stp_info->vlan_list), node); switch_free(vlan_entry); } return SWITCH_STATUS_SUCCESS; }
switch_status_t switch_api_stp_group_vlans_add(switch_device_t device, switch_handle_t stg_handle, uint16_t vlan_count, switch_handle_t *vlan_handle) { switch_stp_info_t *stp_info = NULL; switch_bd_info_t *bd_info = NULL; switch_stp_vlan_entry_t *vlan_entry = NULL; switch_handle_t bd_handle; int count = 0; if (!SWITCH_STP_HANDLE_VALID(stg_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } stp_info = switch_api_stp_get_internal(stg_handle); if (!stp_info) { return SWITCH_STATUS_INVALID_HANDLE; } for (count = 0; count < vlan_count; count++) { bd_handle = vlan_handle[count]; bd_info = switch_bd_get(bd_handle); if (!bd_info) { return SWITCH_STATUS_INVALID_VLAN_ID; } vlan_entry = switch_malloc(sizeof(switch_stp_vlan_entry_t), 1); if (!vlan_entry) { return SWITCH_STATUS_NO_MEMORY; } memset(vlan_entry, 0 , sizeof(switch_stp_vlan_entry_t)); vlan_entry->bd_handle = bd_handle; bd_info->stp_handle = stg_handle; switch_pd_bd_table_update_entry(device, handle_to_id(bd_handle), bd_info); tommy_list_insert_head(&(stp_info->vlan_list), &(vlan_entry->node), vlan_entry); } return SWITCH_STATUS_SUCCESS; }
void switch_l3_hash_key_init(uchar *key, switch_handle_t vrf, switch_ip_addr_t *ip_addr, uint32_t *len, uint32_t *hash) { *len = 0; memset(key, 0, SWITCH_L3_HASH_KEY_SIZE); *(unsigned int *)(&key[0]) = (unsigned int)handle_to_id(vrf); key[4] = ip_addr->type; if (ip_addr->type == SWITCH_API_IP_ADDR_V4) { *(unsigned int *)(&key[5]) = ip_addr->ip.v4addr; *len = 9; } else { memcpy(&key[5], ip_addr->ip.v6addr, 4 * sizeof(unsigned int)); *len = 21; } key[*len] = ip_addr->prefix_len; (*len)++; *hash = MurmurHash2(key, *len, 0x98761234); }
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_status_t switch_api_stp_port_state_set(switch_device_t device, switch_handle_t stg_handle, switch_handle_t handle, switch_stp_state_t state) { switch_stp_info_t *stp_info = NULL; switch_interface_info_t *intf_info = NULL; switch_stp_port_entry_t *port_entry = NULL; tommy_node *node = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_handle_t intf_handle; switch_handle_type_t handle_type = 0; bool new_entry = FALSE; if (!SWITCH_STP_HANDLE_VALID(stg_handle)) { return SWITCH_STATUS_INVALID_HANDLE; } if ((!SWITCH_PORT_HANDLE_VALID(handle)) && (!SWITCH_LAG_HANDLE_VALID(handle)) && (!SWITCH_INTERFACE_HANDLE_VALID(handle))) { return SWITCH_STATUS_INVALID_HANDLE; } stp_info = switch_api_stp_get_internal(stg_handle); if (!stp_info) { return SWITCH_STATUS_INVALID_HANDLE; } handle_type = switch_handle_get_type(handle); intf_handle = handle; if (handle_type == SWITCH_HANDLE_TYPE_PORT || handle_type == SWITCH_HANDLE_TYPE_LAG) { status = switch_interface_handle_get( handle, 0x0, &intf_handle); if (status != SWITCH_STATUS_SUCCESS) { SWITCH_API_ERROR("stp port state set failed"); return status; } } intf_info = switch_api_interface_get(intf_handle); if (!intf_info) { return SWITCH_STATUS_INVALID_INTERFACE; } if (SWITCH_INTF_IS_PORT_L3(intf_info)) { return SWITCH_STATUS_INVALID_INTERFACE; } node = tommy_list_head(&stp_info->port_list); while (node) { port_entry = node->data; if (port_entry->intf_handle == intf_handle) { port_entry->intf_state = state; break; } node = node->next; } if (state == SWITCH_PORT_STP_STATE_NONE) { if (!node) { return SWITCH_STATUS_ITEM_NOT_FOUND; } status = switch_stp_update_flood_list(device, stg_handle, intf_handle, state); status = switch_pd_spanning_tree_table_delete_entry(device, port_entry->hw_entry); tommy_list_remove_existing(&(stp_info->port_list), &(port_entry->node)); switch_free(port_entry); } else { if (!node) { new_entry = TRUE; port_entry = switch_malloc(sizeof(switch_stp_port_entry_t), 1); if (!port_entry) { return SWITCH_STATUS_NO_MEMORY; } memset(port_entry, 0, sizeof(switch_stp_port_entry_t)); port_entry->intf_handle = intf_handle; port_entry->intf_state = state; tommy_list_insert_head(&(stp_info->port_list), &(port_entry->node), port_entry); } status = switch_stp_update_flood_list(device, stg_handle, intf_handle, state); if (new_entry) { status = switch_pd_spanning_tree_table_add_entry(device, handle_to_id(stg_handle), intf_info->ifindex, port_entry->intf_state, &port_entry->hw_entry); } else { status = switch_pd_spanning_tree_table_update_entry(device, handle_to_id(stg_handle), intf_info->ifindex, port_entry->intf_state, port_entry->hw_entry); } } return status; }
switch_status_t switch_api_packet_net_filter_rx_create( switch_device_t device, switch_packet_rx_key_t *rx_key, switch_packet_rx_action_t *rx_action) { switch_hostif_info_t *hostif_info = NULL; switch_lag_info_t *lag_info = NULL; switch_port_info_t *port_info = NULL; switch_packet_rx_entry_t rx_entry; switch_packet_rx_info_t *rx_info = NULL; switch_handle_type_t handle_type = 0; switch_interface_info_t *intf_info = NULL; switch_handle_t bd_handle = 0; switch_bd_info_t *bd_info = NULL; switch_ifindex_t ifindex = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!rx_key || !rx_action) { SWITCH_API_ERROR("filter rx create failed. invalid params"); return SWITCH_STATUS_INVALID_PARAMETER; } memset(&rx_entry, 0x0, sizeof(rx_entry)); if (rx_key->port_lag_valid) { handle_type = switch_handle_get_type(rx_key->port_lag_handle); if (handle_type == SWITCH_HANDLE_TYPE_LAG) { lag_info = switch_api_lag_get_internal(rx_key->port_lag_handle); if (!lag_info) { SWITCH_API_ERROR("invalid lag handle"); return SWITCH_STATUS_INVALID_HANDLE; } ifindex = lag_info->ifindex; } else { port_info = switch_api_port_get_internal(rx_key->port_lag_handle); if (!port_info) { SWITCH_API_ERROR("invalid port handle"); return SWITCH_STATUS_INVALID_HANDLE; } ifindex = port_info->ifindex; } rx_entry.ifindex_valid = TRUE; } if (rx_key->handle_valid) { bd_handle = rx_key->handle; handle_type = switch_handle_get_type(rx_key->handle); if (handle_type == SWITCH_HANDLE_TYPE_INTERFACE) { intf_info = switch_api_interface_get(rx_key->handle); if (!intf_info) { SWITCH_API_ERROR("intf_handle %lx is invalid", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } if (!SWITCH_INTF_IS_PORT_L3(intf_info)) { SWITCH_API_ERROR("intf_handle %lx is not l3", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } bd_handle = intf_info->bd_handle; } bd_info = switch_bd_get(bd_handle); if (!bd_info) { SWITCH_API_ERROR("bd derivation failed %lx", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } rx_entry.bd_valid = TRUE; } if (rx_action->hostif_handle) { hostif_info = switch_hostif_get(rx_action->hostif_handle); if (!hostif_info) { SWITCH_API_ERROR("invalid hostif handle"); return SWITCH_STATUS_INVALID_HANDLE; } } rx_entry.bd = handle_to_id(bd_handle); rx_entry.ifindex = ifindex; rx_entry.port_valid = rx_key->port_valid; rx_entry.port = handle_to_id(rx_key->port_handle); rx_entry.reason_code_valid = rx_key->reason_code_valid; rx_entry.reason_code = rx_key->reason_code; rx_entry.reason_code_mask = rx_key->reason_code_mask; rx_entry.priority = rx_key->priority; rx_info = switch_malloc(sizeof(switch_packet_rx_info_t), 0x1); if (!rx_info) { SWITCH_API_ERROR("port %lx port_lag %lx handle %lx malloc failed", rx_key->port_handle, rx_key->port_lag_handle, rx_key->handle); return SWITCH_STATUS_NO_MEMORY; } memset(rx_info, 0x0, sizeof(switch_packet_rx_info_t)); memcpy(&rx_info->rx_entry, &rx_entry, sizeof(rx_entry)); rx_info->vlan_id = rx_action->vlan_id; rx_info->vlan_action = rx_action->vlan_action; if (hostif_info) { rx_info->intf_fd = hostif_info->intf_fd; } SWITCH_API_INFO( "net_filter_rx_create: port 0x%lx, port_lag_hdl = 0x%lx, " "if_bd_hdl 0x%lx, rcode 0x%x, rcode_mask 0x%x " "vlan_id %d, fd %d, action %d\n", rx_key->port_valid ? rx_key->port_handle : 0, rx_key->port_lag_valid ? rx_key->port_lag_handle : 0, rx_key->handle_valid ? rx_key->handle : 0, rx_key->reason_code_valid ? rx_key->reason_code : 0, rx_key->reason_code_mask, rx_info->vlan_id, rx_info->vlan_action, rx_info->intf_fd); /* * Adding an element to the list results in sorting the list. * tommy does not have a way to compare and insert the elements */ tommy_list_insert_head(&packet_rx_filter_list, &(rx_info->node), rx_info); tommy_list_sort(&packet_rx_filter_list, switch_packet_rx_filter_priority_compare); 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_packet_net_filter_rx_delete( switch_device_t device, switch_packet_rx_key_t *rx_key) { switch_lag_info_t *lag_info = NULL; switch_port_info_t *port_info = NULL; switch_packet_rx_entry_t *tmp_rx_entry = NULL; switch_packet_rx_entry_t rx_entry; switch_packet_rx_info_t *tmp_rx_info = NULL; switch_handle_type_t handle_type = 0; switch_interface_info_t *intf_info = NULL; switch_handle_t bd_handle = 0; switch_bd_info_t *bd_info = NULL; tommy_node *node = NULL; bool node_found = FALSE; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!rx_key) { SWITCH_API_ERROR("filter rx delete failed. invalid params"); return SWITCH_STATUS_INVALID_PARAMETER; } memset(&rx_entry, 0, sizeof(switch_packet_rx_entry_t)); if (rx_key->port_lag_valid && rx_key->port_lag_handle) { handle_type = switch_handle_get_type(rx_key->port_lag_handle); if (handle_type == SWITCH_HANDLE_TYPE_LAG) { lag_info = switch_api_lag_get_internal(rx_key->port_lag_handle); if (!lag_info) { SWITCH_API_ERROR("invalid lag handle"); return SWITCH_STATUS_INVALID_HANDLE; } rx_entry.ifindex = lag_info->ifindex; } else { port_info = switch_api_port_get_internal(rx_key->port_lag_handle); if (!port_info) { SWITCH_API_ERROR("invalid port handle"); return SWITCH_STATUS_INVALID_HANDLE; } rx_entry.ifindex = port_info->ifindex; } } if (rx_key->handle_valid) { bd_handle = rx_key->handle; handle_type = switch_handle_get_type(rx_key->handle); if (handle_type == SWITCH_HANDLE_TYPE_INTERFACE) { intf_info = switch_api_interface_get(rx_key->handle); if (!intf_info) { SWITCH_API_ERROR("intf_handle %lx is invalid", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } if (!SWITCH_INTF_IS_PORT_L3(intf_info)) { SWITCH_API_ERROR("intf_handle %lx is not l3", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } bd_handle = intf_info->bd_handle; } bd_info = switch_bd_get(bd_handle); if (!bd_info) { SWITCH_API_ERROR("bd derivation failed %lx", rx_key->handle); return SWITCH_STATUS_INVALID_HANDLE; } rx_entry.bd = handle_to_id(bd_handle); } if (rx_entry.port_valid) { rx_entry.port = handle_to_id(rx_key->port_handle); } rx_entry.bd_valid = rx_key->handle_valid; rx_entry.reason_code = rx_key->reason_code; node = tommy_list_head(&packet_rx_filter_list); while (node) { tmp_rx_info = (switch_packet_rx_info_t *)node->data; tmp_rx_entry = &tmp_rx_info->rx_entry; if (switch_packet_rx_filter_match(tmp_rx_entry, &rx_entry)) { node_found = TRUE; break; } node = node->next; } if (!node_found) { SWITCH_API_ERROR("tx filter delete failed. node find failed"); return SWITCH_STATUS_ITEM_NOT_FOUND; } tommy_list_remove_existing(&packet_rx_filter_list, node); switch_free(tmp_rx_info); return status; }
switch_status_t switch_api_neighbor_entry_add_tunnel_rewrite( switch_device_t device, switch_neighbor_info_t *neighbor_info) { switch_interface_info_t *intf_info = NULL; switch_api_neighbor_t *neighbor = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; uint16_t smac_index = 1; uint16_t dmac_index = 0; uint16_t sip_index = 0; uint16_t dip_index = 0; switch_handle_t vrf_handle = 0; switch_ip_encap_t *ip_encap = NULL; switch_mpls_encap_t *mpls_encap = NULL; switch_tunnel_info_t *tunnel_info = NULL; switch_ip_addr_t *src_ip = NULL; switch_ip_addr_t *dst_ip = NULL; switch_encap_type_t encap_type = SWITCH_API_ENCAP_TYPE_NONE; neighbor = &neighbor_info->neighbor; intf_info = switch_api_interface_get(neighbor->interface); if (!intf_info) { SWITCH_API_ERROR( "%s:%d: invalid interface for tunnel rewrite!", __FUNCTION__, __LINE__); return SWITCH_STATUS_INVALID_INTERFACE; } tunnel_info = &(SWITCH_INTF_TUNNEL_INFO(intf_info)); dmac_index = switch_dmac_rewrite_insert_hash(device, &neighbor->mac_addr); if (tunnel_info->encap_mode == SWITCH_API_TUNNEL_ENCAP_MODE_IP) { ip_encap = &(SWITCH_INTF_TUNNEL_IP_ENCAP(intf_info)); vrf_handle = ip_encap->vrf_handle; encap_type = SWITCH_INTF_TUNNEL_ENCAP_TYPE(intf_info); src_ip = &ip_encap->src_ip; sip_index = switch_tunnel_src_vtep_index_get(vrf_handle, encap_type, src_ip); dst_ip = &ip_encap->dst_ip; dip_index = switch_tunnel_dst_vtep_index_get(vrf_handle, encap_type, dst_ip); status = switch_pd_tunnel_rewrite_table_add_entry( device, handle_to_id(neighbor->interface), sip_index, dip_index, smac_index, dmac_index, &neighbor_info->rewrite_entry); } else if (tunnel_info->encap_mode == SWITCH_API_TUNNEL_ENCAP_MODE_MPLS) { mpls_encap = &(SWITCH_INTF_TUNNEL_MPLS_ENCAP(intf_info)); status = switch_pd_tunnel_rewrite_table_mpls_add_entry( device, handle_to_id(neighbor->interface), smac_index, dmac_index, mpls_encap, &neighbor_info->rewrite_entry); } if (status != SWITCH_STATUS_SUCCESS) { SWITCH_API_ERROR( "%s:%d unable to add tunnel rewrite entry", __FUNCTION__, __LINE__); return status; } return status; }
switch_status_t switch_api_neighbor_entry_add_rewrite( switch_device_t device, switch_handle_t neighbor_handle, switch_neighbor_info_t *neighbor_info) { switch_status_t status = SWITCH_STATUS_SUCCESS; uint16_t nhop_index = 0; switch_api_neighbor_t *neighbor = NULL; switch_interface_info_t *intf_info = NULL; switch_tunnel_info_t *tunnel_info = NULL; uint16_t tunnel_index = 0; switch_encap_type_t encap_type = 0; uint16_t bd = 0; neighbor = &neighbor_info->neighbor; nhop_index = handle_to_id(neighbor->nhop_handle); 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; } if (intf_info->ln_bd_handle) { bd = handle_to_id(intf_info->ln_bd_handle); } else { bd = handle_to_id(intf_info->bd_handle); } if (neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_SWAP_L2VPN || neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_SWAP_L3VPN || neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_SWAP_PUSH_L2VPN || neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_SWAP_PUSH_L3VPN || neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_PUSH_L2VPN || neighbor->neigh_type == SWITCH_API_NEIGHBOR_MPLS_PUSH_L3VPN) { tunnel_index = handle_to_id(neighbor->interface); status = switch_pd_rewrite_table_mpls_rewrite_add_entry( device, bd, nhop_index, tunnel_index, neighbor->neigh_type, neighbor->mac_addr, neighbor->mpls_label, neighbor->header_count, &neighbor_info->rewrite_entry); } else if (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_TUNNEL) { tunnel_index = handle_to_id(neighbor->interface); tunnel_info = &(SWITCH_INTF_TUNNEL_INFO(intf_info)); if (tunnel_info->encap_mode == SWITCH_API_TUNNEL_ENCAP_MODE_IP) { encap_type = SWITCH_INTF_TUNNEL_ENCAP_TYPE(intf_info); status = switch_pd_rewrite_table_tunnel_rewrite_add_entry( device, bd, nhop_index, neighbor->mac_addr, neighbor->neigh_type, neighbor->rw_type, tunnel_index, encap_type, &neighbor_info->rewrite_entry); } } else { status = switch_pd_rewrite_table_unicast_rewrite_add_entry( device, bd, nhop_index, neighbor->mac_addr, neighbor->rw_type, &neighbor_info->rewrite_entry); } switch_neighbor_dmac_insert_hash( device, intf_info->bd_handle, &neighbor->mac_addr, neighbor_handle); if (status != SWITCH_STATUS_SUCCESS) { SWITCH_API_ERROR( "%s:%d: Unable to add unicast rewrite entry!.", __FUNCTION__, __LINE__); } return status; }
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_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_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_status_t switch_api_packet_net_filter_tx_create( switch_device_t device, switch_packet_tx_key_t *tx_key, switch_packet_tx_action_t *tx_action) { switch_packet_tx_entry_t tx_entry; switch_packet_tx_info_t *tx_info = NULL; switch_hostif_info_t *hostif_info = NULL; switch_handle_t bd_handle = 0; switch_interface_info_t *intf_info = NULL; switch_handle_type_t handle_type = 0; switch_bd_info_t *bd_info = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!tx_key || !tx_action) { SWITCH_API_ERROR("filter tx create failed. invalid params"); return SWITCH_STATUS_INVALID_PARAMETER; } if (tx_key->handle_valid) { hostif_info = switch_hostif_get(tx_key->hostif_handle); if (!hostif_info) { SWITCH_API_ERROR("invalid hostif handle"); return SWITCH_STATUS_INVALID_HANDLE; } } memset(&tx_entry, 0x0, sizeof(tx_entry)); if (tx_key->handle_valid) { tx_entry.intf_fd = hostif_info->intf_fd; } tx_entry.fd_valid = tx_key->handle_valid; tx_entry.vlan_id = tx_key->vlan_id; tx_entry.vlan_valid = tx_key->vlan_valid; tx_entry.priority = tx_key->priority; tx_info = switch_malloc(sizeof(switch_packet_tx_info_t), 0x1); if (!tx_info) { SWITCH_API_ERROR("hif %lx vlan %x malloc failure", tx_key->hostif_handle, tx_key->vlan_id); return SWITCH_STATUS_NO_MEMORY; } if (tx_action->bypass_flags != SWITCH_BYPASS_ALL) { bd_handle = tx_action->handle; handle_type = switch_handle_get_type(tx_action->handle); if (handle_type == SWITCH_HANDLE_TYPE_INTERFACE) { intf_info = switch_api_interface_get(tx_action->handle); if (!intf_info) { SWITCH_API_ERROR("intf_handle %lx is invalid", tx_action->handle); return SWITCH_STATUS_INVALID_HANDLE; } if (!SWITCH_INTF_IS_PORT_L3(intf_info)) { SWITCH_API_ERROR("intf_handle %lx is not l3", tx_action->handle); return SWITCH_STATUS_INVALID_HANDLE; } bd_handle = intf_info->bd_handle; } bd_info = switch_bd_get(bd_handle); if (!bd_info) { SWITCH_API_ERROR( "hif %lx vlan %x invalid bd", tx_key->hostif_handle, tx_key->vlan_id); return SWITCH_STATUS_INVALID_HANDLE; } } memcpy(&tx_info->tx_entry, &tx_entry, sizeof(tx_entry)); tx_info->bd = handle_to_id(bd_handle); tx_info->bypass_flags = tx_action->bypass_flags; tx_info->port = handle_to_id(tx_action->port_handle); SWITCH_API_INFO( "net_filter_tx_create: hostif 0x%lx, vlan_id = %d, fd 0x%x, bypass " "0x%x\n", tx_key->hostif_handle, tx_key->vlan_valid ? tx_key->vlan_id : 0xFFF, tx_entry.intf_fd, tx_info->bypass_flags); tommy_list_insert_head(&packet_tx_filter_list, &(tx_info->node), tx_info); tommy_list_sort(&packet_tx_filter_list, switch_packet_tx_filter_priority_compare); return status; }
switch_handle_t switch_api_sflow_session_create( switch_device_t device, switch_api_sflow_session_info_t *api_sflow_info) { #ifdef P4_SFLOW_ENABLE switch_handle_t sflow_handle = SWITCH_API_INVALID_HANDLE; switch_sflow_info_t *sflow_info = NULL; switch_status_t status = SWITCH_STATUS_FAILURE; // Parameter validation if (api_sflow_info->collector_type != SFLOW_COLLECTOR_TYPE_CPU) { // Only sflow via cpu is supported at this time return SWITCH_API_INVALID_HANDLE; } else if (!switch_port_is_cpu_port(api_sflow_info->egress_port_hdl)) { return SWITCH_API_INVALID_HANDLE; } if (api_sflow_info->sample_mode != SWITCH_SFLOW_SAMPLE_PKT) { // single packet per notificaiton - other modes are TBD return SWITCH_API_INVALID_HANDLE; } if (api_sflow_info->sample_rate == 0) { return SWITCH_API_INVALID_HANDLE; } sflow_handle = switch_sflow_handle_create(); if (sflow_handle == SWITCH_API_INVALID_HANDLE) { return sflow_handle; } sflow_info = switch_sflow_info_get(sflow_handle); if (!sflow_info) { return SWITCH_API_INVALID_HANDLE; } sflow_info->session_id = handle_to_id(sflow_handle); sflow_info->api_info = *api_sflow_info; tommy_list_init(&sflow_info->match_list); sflow_info->mirror_hdl = SWITCH_API_INVALID_HANDLE; sflow_info->mirror_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; sflow_info->ing_take_sample_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; // Create a mirror session to send sampled pkts to CPU. // SWITCH_CPU_MIRROR_SESSION_ID mirror-session can be used, except // it does not truncate the packet. sFlow may not need entire packet. // CPU can perform tuncation as well, but this makes it a bit easier // for CPU if (api_sflow_info->collector_type == SFLOW_COLLECTOR_TYPE_CPU) { switch_api_mirror_info_t api_mirror_info; memset(&api_mirror_info, 0, sizeof(switch_api_mirror_info_t)); api_mirror_info.mirror_type = SWITCH_MIRROR_TYPE_LOCAL; // mirror session id is allocated by the mirroring api api_mirror_info.session_type = SWITCH_MIRROR_SESSION_TYPE_SIMPLE; api_mirror_info.egress_port = CPU_PORT_ID; api_mirror_info.direction = SWITCH_API_DIRECTION_BOTH; api_mirror_info.max_pkt_len = api_sflow_info->extract_len; sflow_info->mirror_hdl = switch_api_mirror_session_create(device, &api_mirror_info); if (sflow_info->mirror_hdl == SWITCH_API_INVALID_HANDLE) { goto error_return; } } else { assert(0); } status = switch_pd_sflow_session_create(device, sflow_info); if (status != SWITCH_STATUS_SUCCESS) { goto error_return; } return sflow_handle; error_return: switch_api_sflow_session_delete(device, sflow_handle, false); return SWITCH_API_INVALID_HANDLE; #else (void)device; (void)api_sflow_info; return SWITCH_API_INVALID_HANDLE; #endif }