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_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_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_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; }