int IPACM_LanToLan::del_offload_link(ipa_ip_type iptype, IPACM_Lan* client, IPACM_Lan* peer, offload_link_info* link) { if(client == NULL || peer == NULL || link == NULL) { IPACMERR("Either iface or link is NULL.\n"); return IPACM_FAILURE; } IPACMDBG_H("Delete an offload link for IP type: %d\n", iptype); int res = IPACM_SUCCESS; if(client->del_lan2lan_flt_rule(iptype, link->flt_rule_hdl) == IPACM_FAILURE) { IPACMERR("Failed to delete flt rule.\n"); res = IPACM_FAILURE; } if(peer->del_lan2lan_rt_rule(iptype, link->rt_rule_hdl) == IPACM_FAILURE) { IPACMERR("Failed to delete rt rules.\n"); res = IPACM_FAILURE; } if(peer->del_lan2lan_hdr(iptype, link->hdr_hdl) == IPACM_FAILURE) { IPACMERR("Failed to delete header.\n"); res = IPACM_FAILURE; } return res; }
int IPACM_LanToLan::clear_peer_list(client_info* client) { if(client == NULL) { IPACMERR("Client is NULL.\n"); return IPACM_FAILURE; } bool err_flag; peer_info_list::iterator client_it; peer_info_list::iterator peer_it; client_info* peer; for(client_it = client->peer.begin(); client_it != client->peer.end(); client_it++) { err_flag = true; peer = client_it->peer_pointer; for(peer_it = peer->peer.begin(); peer_it != peer->peer.end(); peer_it++) { if(peer_it->peer_pointer == client) { peer->peer.erase(peer_it); err_flag = false; break; } } if(err_flag == true) { IPACMERR("Failed to find peer info.\n"); return IPACM_FAILURE; } } client->peer.clear(); return IPACM_SUCCESS; }
bool IPACM_Routing::ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *mdfyRules) { int retval = 0, cnt; if (!DeviceNodeIsOpened()) { IPACMERR("Device is not opened\n"); return false; } retval = ioctl(m_fd, IPA_IOC_MDFY_RT_RULE, mdfyRules); if (retval) { IPACMERR("Failed modifying routing rules %p\n", mdfyRules); return false; } for(cnt=0; cnt<mdfyRules->num_rules; cnt++) { if(mdfyRules->rules[cnt].status != 0) { IPACMERR("Unable to modify rule: %d\n", cnt); } } IPACMDBG_H("Modified routing rules %p\n", mdfyRules); return true; }
int IPACM_Config::Init(void) { /* Read IPACM Config file */ char IPACM_config_file[IPA_MAX_FILE_LEN]; IPACM_conf_t *cfg; cfg = (IPACM_conf_t *)malloc(sizeof(IPACM_conf_t)); if(cfg == NULL) { IPACMERR("Unable to allocate cfg memory.\n"); return IPACM_FAILURE; } uint32_t subnet_addr; uint32_t subnet_mask; int i, ret = IPACM_SUCCESS; struct in_addr in_addr_print; m_fd = open(DEVICE_NAME, O_RDWR); if (0 > m_fd) { IPACMERR("Failed opening %s.\n", DEVICE_NAME); } strncpy(IPACM_config_file, "/etc/IPACM_cfg.xml", sizeof(IPACM_config_file)); IPACMDBG_H("\n IPACM XML file is %s \n", IPACM_config_file); if (IPACM_SUCCESS == ipacm_read_cfg_xml(IPACM_config_file, cfg)) { IPACMDBG_H("\n IPACM XML read OK \n"); } else { IPACMERR("\n IPACM XML read failed \n"); ret = IPACM_FAILURE; goto fail; } /* Check wlan AP-AP access mode configuration */ if (cfg->num_wlan_guest_ap == 2) { IPACMDBG_H("IPACM_Config::Both wlan APs can not be configured in guest ap mode. \n"); IPACMDBG_H("IPACM_Config::configure both APs in full access mode or at least one in guest ap mode. \n"); ret = IPACM_FAILURE; goto fail; } /* Construct IPACM Iface table */ ipa_num_ipa_interfaces = cfg->iface_config.num_iface_entries; if (iface_table != NULL) { free(iface_table); iface_table = NULL; IPACMDBG_H("RESET IPACM_Config::iface_table\n"); } iface_table = (ipa_ifi_dev_name_t *)calloc(ipa_num_ipa_interfaces, sizeof(ipa_ifi_dev_name_t)); if(iface_table == NULL) { IPACMERR("Unable to allocate iface_table memory.\n"); ret = IPACM_FAILURE; <<<<<<< HEAD
int IPACM_LanToLan::turnoff_offload_links(ipa_ip_type iptype, client_info* client) { if(client == NULL) { IPACMERR("Client is NULL.\n"); return IPACM_FAILURE; } bool err_flag; offload_link_info_list::iterator client_it; offload_link_info_list::iterator peer_it; client_info* peer; for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) { peer = client_it->peer_pointer; if(del_offload_link(iptype, client->p_iface, peer->p_iface, &(*client_it)) == IPACM_FAILURE) { IPACMERR("Failed to delete client's offload link.\n"); return IPACM_FAILURE; } err_flag = true; for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) { if(peer_it->peer_pointer == client) { if(del_offload_link(iptype, peer->p_iface, client->p_iface, &(*peer_it)) == IPACM_FAILURE) { IPACMERR("Failed to delete peer's offload link.\n"); return IPACM_FAILURE; } peer->link.erase(peer_it); err_flag = false; break; } } if(err_flag) { IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); return IPACM_FAILURE; } if(iptype == IPA_IP_v4) { num_offload_pair_v4_ --; IPACMDBG_H("Now the number of v4 offload pair is %d\n", num_offload_pair_v4_); } else { num_offload_pair_v6_ --; IPACMDBG_H("Now the number of v6 offload pair is %d\n", num_offload_pair_v6_); } } client->link.clear(); return IPACM_SUCCESS; }
void IPACM_LanToLan_Iface::handle_intra_interface_info() { uint32_t hdr_proc_ctx_hdl; if(m_p_iface->tx_prop == NULL) { IPACMERR("No tx prop.\n"); return; } m_intra_interface_info.peer = this; snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, "eth_v4_intra_interface"); IPACMDBG_H("IPv4 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4]); snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, "eth_v6_intra_interface"); IPACMDBG_H("IPv6 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6]); memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX); IPACMDBG_H("IPv4 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4]); memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX); IPACMDBG_H("IPv6 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6]); m_p_iface->eth_bridge_add_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type, &hdr_proc_ctx_hdl); hdr_proc_ctx_for_intra_interface = hdr_proc_ctx_hdl; IPACMDBG_H("Hdr proc ctx for intra-interface communication: hdl %d\n", hdr_proc_ctx_hdl); return; }
int IPACM_LanToLan::add_flt_rules(ipa_ip_type iptype, client_info* client) { if(client == NULL) { IPACMERR("No client info is found.\n"); return IPACM_FAILURE; } bool err_flag; offload_link_info_list::iterator client_it; offload_link_info_list::iterator peer_it; client_info* peer; for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) { peer = client_it->peer_pointer; if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, client->ip.ipv6_addr, peer->ip.ipv6_addr, &(client_it->flt_rule_hdl)) == IPACM_FAILURE) { IPACMERR("Failed to add client's filtering rule.\n"); return IPACM_FAILURE; } err_flag = true; for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) { if(peer_it->peer_pointer == client) { if(peer->p_iface->add_lan2lan_flt_rule(iptype, peer->ip.ipv4_addr, client->ip.ipv4_addr, peer->ip.ipv6_addr, client->ip.ipv6_addr, &(peer_it->flt_rule_hdl)) == IPACM_FAILURE) { IPACMERR("Failed to delete peer's offload link.\n"); return IPACM_FAILURE; } err_flag = false; break; } } if(err_flag) { IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); return IPACM_FAILURE; } } return IPACM_SUCCESS; }
IPACM_Routing::IPACM_Routing() { m_fd = open(DEVICE_NAME, O_RDWR); if (0 == m_fd) { IPACMERR("Failed opening %s.\n", DEVICE_NAME); } }
bool IPACM_Routing::DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip) { const uint8_t NUM_RULES = 1; struct ipa_ioc_del_rt_rule *rt_rule; struct ipa_rt_rule_del *rt_rule_entry; bool res = true; int len = 0; if (rt_rule_hdl == 0) { IPACMERR(" No route handle passed. Ignoring it\n"); return res; } len = (sizeof(struct ipa_ioc_del_rt_rule)) + (NUM_RULES * sizeof(struct ipa_rt_rule_del)); rt_rule = (struct ipa_ioc_del_rt_rule *)malloc(len); if (rt_rule == NULL) { IPACMERR("unable to allocate memory for del route rule\n"); return false; } memset(rt_rule, 0, len); rt_rule->commit = 1; rt_rule->num_hdls = NUM_RULES; rt_rule->ip = ip; rt_rule_entry = &rt_rule->hdl[0]; rt_rule_entry->status = -1; rt_rule_entry->hdl = rt_rule_hdl; IPACMDBG_H("Deleting Route hdl:(0x%x) with ip type: %d\n", rt_rule_entry->hdl, ip); if ((false == DeleteRoutingRule(rt_rule)) || (rt_rule_entry->status)) { PERROR("Routing rule deletion failed!\n"); goto fail; res = false; } fail: free(rt_rule); return res; }
void IPACM_LanToLan::handle_del_connection(ipacm_event_connection* new_conn) { #ifdef CT_OPT if(new_conn == NULL) { IPACMERR("No connection info is found.\n"); return; } if(new_conn->iptype != IPA_IP_v4 && new_conn->iptype != IPA_IP_v6) { IPACMERR("IP type is not expected: %d.\n", new_conn->iptype); return; } IPACMDBG_H("Del connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", new_conn->iptype, new_conn->src_ipv4_addr, new_conn->dst_ipv4_addr); IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", new_conn->src_ipv6_addr[0], new_conn->src_ipv6_addr[1], new_conn->src_ipv6_addr[2], new_conn->src_ipv6_addr[3], new_conn->dst_ipv6_addr[0], new_conn->dst_ipv6_addr[1], new_conn->dst_ipv6_addr[2], new_conn->dst_ipv6_addr[3]); if(is_lan2lan_connection(new_conn) == false) { IPACMDBG_H("The connection is not lan2lan connection.\n"); remove_cache_connection(new_conn); return; } ipacm_cmd_q_data evt; ipacm_event_connection* conn; conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); if(conn == NULL) { IPACMERR("Failed to allocate memory for del_connection event.\n"); return; } memcpy(conn, new_conn, sizeof(ipacm_event_connection)); memset(&evt, 0, sizeof(evt)); evt.event = IPA_LAN_TO_LAN_DEL_CONNECTION; evt.evt_data = (void*)conn; IPACM_EvtDispatcher::PostEvt(&evt); #endif return; }
bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) { int retval = 0, cnt=0; bool isInvalid = false; if (!DeviceNodeIsOpened()) { IPACMERR("Device is not opened\n"); return false; } for(cnt=0; cnt<ruleTable->num_rules; cnt++) { if(ruleTable->rules[cnt].rule.dst > IPA_CLIENT_MAX) { IPACMERR("Invalid dst pipe, Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); isInvalid = true; } } if(isInvalid) { return false; } retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE, ruleTable); if (retval) { IPACMERR("Failed adding routing rule %p\n", ruleTable); return false; } for(cnt=0; cnt<ruleTable->num_rules; cnt++) { IPACMDBG("Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); } IPACMDBG_H("Added routing rule %p\n", ruleTable); return true; }
void IPACM_LanToLan::handle_client_power_save(ipacm_event_lan_client* data) { if(data == NULL) { IPACMERR("No client info is found.\n"); return; } if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) { IPACMERR("Event data is not populated properly.\n"); return; } if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) { IPACMERR("IP type is not expected: %d.\n", data->iptype); return; } IPACMDBG_H("Client power save info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", data->p_iface->dev_name, data->iptype, data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); client_info* client_ptr; uint64_t v6_addr; if(data->iptype == IPA_IP_v4) { if(client_info_v4_.count(data->ipv4_addr) == 0)//if not found the client, return { IPACMERR("The client is not found the client, return.\n"); return; } IPACMDBG_H("The client is found.\n"); client_info& client = client_info_v4_[data->ipv4_addr]; client_ptr = &client; } else { memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table { IPACMERR("The client is not found the client, return.\n"); return; } IPACMDBG_H("The client is found.\n"); client_info& client = client_info_v6_[v6_addr]; client_ptr = &client; } if(remove_flt_rules(data->iptype, client_ptr) == IPACM_FAILURE) { IPACMERR("Failed to remove flt rules when power save.\n"); return; } client_ptr->is_active = false; client_ptr->is_powersave = true; return; }
//If need to remove an entry in peer list, return true, otherwise return false bool IPACM_LanToLan::remove_connection(client_info* src_client, client_info* dst_client) { if(src_client == NULL || dst_client == NULL) { IPACMERR("Either source or dest client is NULL.\n"); return false; } peer_info_list::iterator it; bool ret = false; for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) { if(it->peer_pointer == dst_client) { it->num_connection--; IPACMDBG_H("Find dst client entry in src peer list, connection count: %d\n", it->num_connection); if(it->num_connection == 0) { IPACMDBG_H("Need to remove dst entry in src peer list.\n"); ret = true; } break; } } if(ret == true) { src_client->peer.erase(it); } ret = false; for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) { if(it->peer_pointer == src_client) { it->num_connection--; IPACMDBG_H("Find src client entry in dst peer list, connection count: %d\n", it->num_connection); if(it->num_connection == 0) { IPACMDBG_H("Need to remove src entry in dst peer list.\n"); ret = true; } break; } } if(ret == true) { dst_client->peer.erase(it); } return ret; }
void IPACM_LanToLan::erase_offload_link(ipa_ip_type iptype, client_info* src_client, client_info* dst_client) { if(src_client == NULL || dst_client == NULL) { IPACMERR("Either source or dest client is NULL.\n"); return; } offload_link_info_list::iterator it; int res_src = IPACM_FAILURE, res_dst = IPACM_FAILURE; for(it = src_client->link.begin(); it != src_client->link.end(); it++) { if(it->peer_pointer == dst_client) { res_src = IPACM_SUCCESS; IPACMDBG_H("Find dst client entry in src link list\n"); res_src = del_offload_link(iptype, src_client->p_iface, dst_client->p_iface, &(*it)); src_client->link.erase(it); break; } } for(it = dst_client->link.begin(); it != dst_client->link.end(); it++) { if(it->peer_pointer == src_client) { res_dst = IPACM_SUCCESS; IPACMDBG_H("Find src client entry in dst link list\n"); res_dst = del_offload_link(iptype, dst_client->p_iface, src_client->p_iface, &(*it)); dst_client->link.erase(it); break; } } if(res_src == IPACM_SUCCESS && res_dst == IPACM_SUCCESS) { if(iptype == IPA_IP_v4) { num_offload_pair_v4_ --; IPACMDBG_H("Decrease num of v4 offload pairs to %d\n", num_offload_pair_v4_); } else { num_offload_pair_v6_ --; IPACMDBG_H("Decrease num of v6 offload pairs to %d\n", num_offload_pair_v6_); } } return; }
//If need to insert an entry in peer list, return true, otherwise return false bool IPACM_LanToLan::add_connection(client_info* src_client, client_info* dst_client) { if(src_client == NULL || dst_client == NULL) { IPACMERR("Either source or dest client is NULL.\n"); return false; } peer_info_list::iterator it; peer_info new_peer; bool ret = false; for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) { if(it->peer_pointer == dst_client) { it->num_connection++; IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); break; } } if(it == src_client->peer.end()) { IPACMDBG_H("Not finding dst client entry, insert a new one in peer list.\n"); new_peer.peer_pointer = dst_client; new_peer.num_connection = 1; src_client->peer.push_back(new_peer); ret = true; } for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) { if(it->peer_pointer == src_client) { it->num_connection++; IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); break; } } if(it == dst_client->peer.end()) { IPACMDBG_H("Not finding src client entry, insert a new one in peer list.\n"); new_peer.peer_pointer = src_client; new_peer.num_connection = 1; dst_client->peer.push_back(new_peer); ret = true; } return ret; }
bool IPACM_Routing::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable) { int retval = 0; if (!DeviceNodeIsOpened()) return false; retval = ioctl(m_fd, IPA_IOC_DEL_RT_RULE, ruleTable); if (retval) { IPACMERR("Failed deleting routing rule table %p\n", ruleTable); return false; } IPACMDBG_H("Deleted routing rule %p\n", ruleTable); return true; }
bool IPACM_Routing::Commit(enum ipa_ip_type ip) { int retval = 0; if (!DeviceNodeIsOpened()) return false; retval = ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); if (retval) { IPACMERR("Failed commiting routing rules.\n"); return false; } IPACMDBG_H("Commited routing rules to IPA HW.\n"); return true; }
bool IPACM_Routing::PutRoutingTable(uint32_t routingTableHandle) { int retval = 0; if (!DeviceNodeIsOpened()) return false; retval = ioctl(m_fd, IPA_IOC_PUT_RT_TBL, routingTableHandle); if (retval) { IPACMERR("IPA_IOCTL_PUT_RT_TBL ioctl failed.\n"); return false; } IPACMDBG_H("IPA_IOCTL_PUT_RT_TBL ioctl issued to IPA routing block.\n"); return true; }
bool IPACM_Routing::Reset(enum ipa_ip_type ip) { int retval = 0; if (!DeviceNodeIsOpened()) return false; retval = ioctl(m_fd, IPA_IOC_RESET_RT, ip); retval |= ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); if (retval) { IPACMERR("Failed resetting routing block.\n"); return false; } IPACMDBG_H("Reset command issued to IPA routing block.\n"); return true; }
bool IPACM_Routing::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable) { int retval = 0; if (!DeviceNodeIsOpened()) return false; retval = ioctl(m_fd, IPA_IOC_GET_RT_TBL, routingTable); if (retval) { IPACMERR("IPA_IOCTL_GET_RT_TBL ioctl failed, routingTable =0x%p, retval=0x%x.\n", routingTable, retval); return false; } IPACMDBG_H("IPA_IOCTL_GET_RT_TBL ioctl issued to IPA routing block.\n"); /* put routing table right after successfully get routing table */ PutRoutingTable(routingTable->hdl); return true; }
void IPACM_LanToLan_Iface::add_client_flt_rule(peer_iface_info *peer, client_info *client, ipa_ip_type iptype) { list<flt_rule_info>::iterator it_flt; uint32_t flt_rule_hdl; flt_rule_info new_flt_info; ipa_ioc_get_rt_tbl rt_tbl; rt_tbl.ip = iptype; memcpy(rt_tbl.name, peer->rt_tbl_name_for_flt[iptype], sizeof(rt_tbl.name)); IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name); if(IPACM_Iface::m_routing.GetRoutingTable(&rt_tbl) == false) { IPACMERR("Failed to get routing table.\n"); return; } m_p_iface->eth_bridge_add_flt_rule(client->mac_addr, rt_tbl.hdl, iptype, &flt_rule_hdl); IPACMDBG_H("Installed flt rule for IP type %d: handle %d\n", iptype, flt_rule_hdl); for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++) { if(it_flt->p_client == client) //the client is already in the flt info list { IPACMDBG_H("The client is found in flt info list.\n"); it_flt->flt_rule_hdl[iptype] = flt_rule_hdl; break; } } if(it_flt == peer->flt_rule.end()) //the client is not in the flt info list { IPACMDBG_H("The client is not found in flt info list, insert a new one.\n"); memset(&new_flt_info, 0, sizeof(new_flt_info)); new_flt_info.p_client = client; new_flt_info.flt_rule_hdl[iptype] = flt_rule_hdl; peer->flt_rule.push_front(new_flt_info); } return; }
void IPACM_LanToLan::check_potential_link(ipa_ip_type iptype, client_info* client) { if(client == NULL) { IPACMERR("Client is NULL.\n"); return; } IPACMDBG_H("Check client's peer list.\n"); IPACMDBG_H("Client: IP type: %d, IPv4 addr: 0x%08x, IPv6 addr: 0x%08x%08x%08x%08x\n", iptype, client->ip.ipv4_addr, client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3]); peer_info_list::iterator peer_it; int res, num = 0; for(peer_it = client->peer.begin(); peer_it != client->peer.end(); peer_it++) { if(peer_it->peer_pointer->is_active == true && peer_it->num_connection > 0) { res = IPACM_SUCCESS; res = add_offload_link(iptype, client, peer_it->peer_pointer); res = add_offload_link(iptype, peer_it->peer_pointer, client); if(res == IPACM_SUCCESS) { if(iptype == IPA_IP_v4) { num_offload_pair_v4_ ++; IPACMDBG_H("Now the number of v4 offload links is %d.\n", num_offload_pair_v4_); } else { num_offload_pair_v6_ ++; IPACMDBG_H("Now the number of v6 offload links is %d.\n", num_offload_pair_v6_); } num++; } } } IPACMDBG_H("Added %d offload links in total.\n", num); return; }
void IPACM_LanToLan::handle_iface_up(ipacm_event_eth_bridge *data) { list<IPACM_LanToLan_Iface>::iterator it; IPACMDBG_H("Interface name: %s IP type: %d\n", data->p_iface->dev_name, data->iptype); for(it = m_iface.begin(); it != m_iface.end(); it++) { if(it->get_iface_pointer() == data->p_iface) { IPACMDBG_H("Found the interface.\n"); if(it->get_m_is_ip_addr_assigned(data->iptype) == false) { IPACMDBG_H("IP type %d was not active before, activating it now.\n", data->iptype); it->set_m_is_ip_addr_assigned(data->iptype, true); /* install inter-interface rules */ if(it->get_m_support_inter_iface_offload()) it->add_all_inter_interface_client_flt_rule(data->iptype); /* install intra-BSS rules */ if(it->get_m_support_intra_iface_offload()) it->add_all_intra_interface_client_flt_rule(data->iptype); } break; } } if(it == m_iface.end()) //If the interface has not been created before { if(m_iface.size() == MAX_NUM_IFACE) { IPACMERR("The number of interfaces has reached maximum %d.\n", MAX_NUM_IFACE); return; } if(!data->p_iface->tx_prop || !data->p_iface->rx_prop) { IPACMERR("The interface %s does not have tx_prop or rx_prop.\n", data->p_iface->dev_name); return; } if(data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_NONE || data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_MAX) { IPACMERR("Invalid l2 header type %s!\n", ipa_l2_hdr_type[data->p_iface->tx_prop->tx[0].hdr_l2_type]); return; } IPACMDBG_H("Does not find the interface, insert a new one.\n"); IPACM_LanToLan_Iface new_iface(data->p_iface); new_iface.set_m_is_ip_addr_assigned(data->iptype, true); m_iface.push_front(new_iface); IPACMDBG_H("Now the total number of interfaces is %d.\n", m_iface.size()); IPACM_LanToLan_Iface &front_iface = m_iface.front(); /* install inter-interface rules */ if(front_iface.get_m_support_inter_iface_offload()) { for(it = ++m_iface.begin(); it != m_iface.end(); it++) { /* add peer info only when both interfaces support inter-interface communication */ if(it->get_m_support_inter_iface_offload()) { /* populate hdr_proc_ctx and routing table handle */ handle_new_iface_up(&front_iface, &(*it)); /* add client specific routing rule on existing interface */ it->add_client_rt_rule_for_new_iface(); } } /* add client specific filtering rule on new interface */ front_iface.add_all_inter_interface_client_flt_rule(data->iptype); } /* populate the intra-interface information */ if(front_iface.get_m_support_intra_iface_offload()) { front_iface.handle_intra_interface_info(); } /* handle cached client add event */ handle_cached_client_add_event(front_iface.get_iface_pointer()); } return; }
void IPACM_LanToLan::handle_new_lan2lan_connection(ipacm_event_connection* data) { IPACMDBG_H("New lan2lan connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", data->iptype, data->src_ipv4_addr, data->dst_ipv4_addr); IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", data->src_ipv6_addr[0], data->src_ipv6_addr[1], data->src_ipv6_addr[2], data->src_ipv6_addr[3], data->dst_ipv6_addr[0], data->dst_ipv6_addr[1], data->dst_ipv6_addr[2], data->dst_ipv6_addr[3]); client_info* src_client_ptr; client_info* dst_client_ptr; if(data->iptype == IPA_IP_v4) { if(client_info_v4_.count(data->src_ipv4_addr) == 0 || client_info_v4_.count(data->dst_ipv4_addr) == 0) { IPACMERR("Either source or destination is not in table.\n"); return; } client_info& src_client = client_info_v4_[data->src_ipv4_addr]; src_client_ptr = &src_client; client_info& dst_client = client_info_v4_[data->dst_ipv4_addr]; dst_client_ptr = &dst_client; } else //ipv6 case { uint64_t src_ipv6_addr; uint64_t dst_ipv6_addr; memcpy(&src_ipv6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); memcpy(&dst_ipv6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); if(client_info_v6_.count(src_ipv6_addr) == 0 || client_info_v6_.count(dst_ipv6_addr) == 0) { IPACMERR("Either source or destination is not in table.\n"); return; } client_info& src_client = client_info_v6_[src_ipv6_addr]; src_client_ptr = &src_client; client_info& dst_client = client_info_v6_[dst_ipv6_addr]; dst_client_ptr = &dst_client; } IPACMDBG_H("Both src and dst are already in table.\n"); bool is_first_connection; is_first_connection = add_connection(src_client_ptr, dst_client_ptr); if(is_first_connection && src_client_ptr->is_active && dst_client_ptr->is_active) { IPACMDBG_H("This is first connection, add offload links.\n"); if(add_offload_link(data->iptype, src_client_ptr, dst_client_ptr) == IPACM_FAILURE) { IPACMERR("Failed to add offload link for src->dst direction.\n"); return; } if(add_offload_link(data->iptype, dst_client_ptr, src_client_ptr) == IPACM_FAILURE) { IPACMERR("Failed to add offload link for dst->src direction.\n"); return; } if(data->iptype == IPA_IP_v4) { num_offload_pair_v4_ ++; IPACMDBG_H("Added offload links, now num_offload_pair_v4_: %d\n", num_offload_pair_v4_); } else { num_offload_pair_v6_ ++; IPACMDBG_H("Added offload links, now num_offload_pair_v6_: %d\n", num_offload_pair_v6_); } } return; }
void IPACM_LanToLan::handle_client_active(ipacm_event_lan_client* data) { if(data == NULL) { IPACMERR("No client info is found.\n"); return; } if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) { IPACMERR("Event data is not populated properly.\n"); return; } if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) { IPACMERR("IP type is not expected.\n"); return; } IPACMDBG_H("New client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", data->p_iface->dev_name, data->iptype, data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); bool client_not_found; client_info* client_ptr; if(data->iptype == IPA_IP_v4) { client_not_found = (client_info_v4_.count(data->ipv4_addr) == 0); IPACMDBG_H("Is the client not found? %d\n", client_not_found); client_info& client = client_info_v4_[data->ipv4_addr]; client_ptr = &client; } else { uint64_t v6_addr; memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); client_not_found = (client_info_v6_.count(v6_addr) == 0); IPACMDBG_H("Is the client not found? %d\n", client_not_found); client_info& client = client_info_v6_[v6_addr]; client_ptr = &client; } if(client_not_found == true) { if(data->iptype == IPA_IP_v4) { client_ptr->ip.ipv4_addr = data->ipv4_addr; } else { memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); } memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); client_ptr->is_active = true; client_ptr->is_powersave = false; client_ptr->p_iface = data->p_iface; generate_new_connection(data->iptype, client_ptr); check_cache_connection(data->iptype, client_ptr); } else //the client is found { if(client_ptr->is_active == true) //the client is active { IPACMDBG_H("The client is active.\n"); if(memcmp(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)) == 0) { IPACMDBG_H("Mac addr is the same, do nothing.\n"); } else { IPACMERR("The new client has same IP but differenc mac.\n"); turnoff_offload_links(data->iptype, client_ptr); clear_peer_list(client_ptr); if(data->iptype == IPA_IP_v4) { client_ptr->ip.ipv4_addr = data->ipv4_addr; } else { memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); } memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); client_ptr->is_active = true; client_ptr->is_powersave = false; client_ptr->p_iface = data->p_iface; generate_new_connection(data->iptype, client_ptr); check_cache_connection(data->iptype, client_ptr); } } else //the client is inactive { IPACMDBG_H("The client is inactive.\n"); if(data->iptype == IPA_IP_v4) { client_ptr->ip.ipv4_addr = data->ipv4_addr; } else { memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); } memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); client_ptr->is_active = true; client_ptr->is_powersave = false; client_ptr->p_iface = data->p_iface; check_potential_link(data->iptype, client_ptr); generate_new_connection(data->iptype, client_ptr); check_cache_connection(data->iptype, client_ptr); } } IPACMDBG_H("There are %d clients in v4 table and %d clients in v6 table.\n", client_info_v4_.size(), client_info_v6_.size()); return; }
int IPACM_EvtDispatcher::PostEvt ( ipacm_cmd_q_data *data ) { Message *item = NULL; MessageQueue *MsgQueue = NULL; if(data->event < IPA_EXTERNAL_EVENT_MAX) { IPACMDBG("Insert event into external queue.\n"); MsgQueue = MessageQueue::getInstanceExternal(); } else { IPACMDBG("Insert event into internal queue.\n"); MsgQueue = MessageQueue::getInstanceInternal(); } if(MsgQueue == NULL) { IPACMERR("unable to retrieve MsgQueue instance\n"); return IPACM_FAILURE; } item = new Message(); if(item == NULL) { IPACMERR("unable to create new message item\n"); return IPACM_FAILURE; } item->evt.callback_ptr = IPACM_EvtDispatcher::ProcessEvt; memcpy(&item->evt.data, data, sizeof(ipacm_cmd_q_data)); if(pthread_mutex_lock(&mutex) != 0) { IPACMERR("unable to lock the mutex\n"); return IPACM_FAILURE; } IPACMDBG("Enqueing item\n"); MsgQueue->enqueue(item); IPACMDBG("Enqueued item %p\n", item); if(pthread_cond_signal(&cond_var) != 0) { IPACMDBG("unable to lock the mutex\n"); /* Release the mutex before you return failure */ if(pthread_mutex_unlock(&mutex) != 0) { IPACMERR("unable to unlock the mutex\n"); return IPACM_FAILURE; } return IPACM_FAILURE; } if(pthread_mutex_unlock(&mutex) != 0) { IPACMERR("unable to unlock the mutex\n"); return IPACM_FAILURE; } return IPACM_SUCCESS; }
void IPACM_LanToLan::handle_client_disconnect(ipacm_event_lan_client* data) { if(data == NULL) { IPACMERR("No client info is found.\n"); return; } if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) { IPACMERR("Event data is not populated properly.\n"); return; } if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) { IPACMERR("IP type is not expected: %d.\n", data->iptype); return; } IPACMDBG_H("Del client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", data->p_iface->dev_name, data->iptype, data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); client_info* client_ptr; uint64_t v6_addr; if(data->iptype == IPA_IP_v4) { if(client_info_v4_.count(data->ipv4_addr) == 0) //if not found the client, return { IPACMERR("The client is not found the client, return.\n"); return; } IPACMDBG_H("The client is found.\n"); client_info& client = client_info_v4_[data->ipv4_addr]; client_ptr = &client; } else { memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table { IPACMERR("The client is not found the client, return.\n"); return; } IPACMDBG_H("The client is found.\n"); client_info& client = client_info_v6_[v6_addr]; client_ptr = &client; } turnoff_offload_links(data->iptype, client_ptr); clear_peer_list(client_ptr); if(data->iptype == IPA_IP_v4) { client_info_v4_.erase(data->ipv4_addr); } else { client_info_v6_.erase(v6_addr); } return; }
void IPACM_LanToLan::check_cache_connection(ipa_ip_type iptype, client_info* client) { #ifdef CT_OPT connection_list::iterator it; if(iptype == IPA_IP_v4) { it = connection_v4_.begin(); while(it != connection_v4_.end()) { if( (it->src_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->dst_ipv4_addr) > 0) || (it->dst_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->src_ipv4_addr) > 0) ) { IPACMDBG("Found a cache connection for src client 0x%08x and dst client 0x%08x.\n", it->src_ipv4_addr, it->dst_ipv4_addr); ipacm_cmd_q_data evt; ipacm_event_connection* conn; conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); if(conn == NULL) { IPACMERR("Failed to allocate memory for new_connection event.\n"); return; } memcpy(conn, &(*it), sizeof(ipacm_event_connection)); memset(&evt, 0, sizeof(evt)); evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; evt.evt_data = (void*)conn; IPACM_EvtDispatcher::PostEvt(&evt); it = connection_v4_.erase(it); IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v4_.size()); } else { it++; } } } else { uint64_t src_v6_addr, dst_v6_addr; it = connection_v6_.begin(); while(it != connection_v6_.end()) { memcpy(&src_v6_addr, &(it->src_ipv6_addr[2]), sizeof(uint64_t)); memcpy(&dst_v6_addr, &(it->dst_ipv6_addr[2]), sizeof(uint64_t)); if( (memcmp(it->src_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(dst_v6_addr) > 0) || (memcmp(it->dst_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(src_v6_addr) > 0) ) { IPACMDBG("Found a cache connection with src client 0x%08x%08x%08x%08x and dst client 0x%08x%08x%08x%08x.\n", it->src_ipv6_addr[0], it->src_ipv6_addr[1], it->src_ipv6_addr[2], it->src_ipv6_addr[3], it->dst_ipv6_addr[0], it->dst_ipv6_addr[1], it->dst_ipv6_addr[2], it->dst_ipv6_addr[3]); ipacm_cmd_q_data evt; ipacm_event_connection* conn; conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); if(conn == NULL) { IPACMERR("Failed to allocate memory for new_connection event.\n"); return; } memcpy(conn, &(*it), sizeof(ipacm_event_connection)); memset(&evt, 0, sizeof(evt)); evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; evt.evt_data = (void*)conn; IPACM_EvtDispatcher::PostEvt(&evt); it = connection_v6_.erase(it); IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v6_.size()); } else { it++; } } } #endif return; }
void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) { int ipa_interface_index; ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param; ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param; ipacm_event_data_all *data_all = (ipacm_event_data_all *)param; ipacm_ifacemgr_data ifmgr_data = {0}; switch(event) { case IPA_CFG_CHANGE_EVENT: IPACMDBG_H(" RESET IPACM_cfg \n"); IPACM_Iface::ipacmcfg->Init(); break; case IPA_BRIDGE_LINK_UP_EVENT: IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n"); ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_BRIDGE_LINK_UP_EVENT: not supported iface id: %d\n", data_all->if_index); break; } /* check if iface is bridge interface*/ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) { IPACM_Iface::ipacmcfg->ipa_bridge_enable = true; memcpy(IPACM_Iface::ipacmcfg->bridge_mac, data_all->mac_addr, sizeof(IPACM_Iface::ipacmcfg->bridge_mac)); IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n", IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2], IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]); } break; case IPA_LINK_UP_EVENT: IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); break; } /* LTE-backhaul */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == EMBMS_IF) { IPACMDBG("WAN-EMBMS (%s) link already up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); } else if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) { IPACMDBG_H("WAN-LTE (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); ifmgr_data.if_index = evt_data->if_index; ifmgr_data.if_type = Q6_WAN; create_iface_instance(&ifmgr_data); } break; case IPA_USB_LINK_UP_EVENT: IPACMDBG_H("Recieved IPA_USB_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_USB_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); break; } /* check if it's WAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) { /* usb-backhaul using sta_mode ECM_WAN*/ IPACMDBG_H("WAN-usb (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, evt_data->if_index); ifmgr_data.if_index = evt_data->if_index; ifmgr_data.if_type = ECM_WAN; create_iface_instance(&ifmgr_data); } else { ifmgr_data.if_index = evt_data->if_index; ifmgr_data.if_type = Q6_WAN; create_iface_instance(&ifmgr_data); } break; case IPA_WLAN_AP_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_WLAN_AP_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); break; } /* change iface category from unknown to WLAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) { IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WLAN_IF; IPACMDBG_H("WLAN AP (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); ifmgr_data.if_index = evt_data->if_index; ifmgr_data.if_type = Q6_WAN; create_iface_instance(&ifmgr_data); } else { IPACMDBG_H("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); } break; case IPA_WLAN_STA_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(StaData->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_WLAN_STA_LINK_UP_EVENT: not supported iface id: %d\n", StaData->if_index); break; } /* change iface category from unknown to WAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) { /* wlan-backhaul using sta_mode WLAN_WAN */ IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WAN_IF; IPACMDBG_H("WLAN STA (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, StaData->if_index); ifmgr_data.if_index = StaData->if_index; ifmgr_data.if_type = WLAN_WAN; memcpy(ifmgr_data.mac_addr, StaData->mac_addr, sizeof(ifmgr_data.mac_addr)); create_iface_instance(&ifmgr_data); } else { IPACMDBG_H("iface %s already up and act as %d mode: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); } break; /* Add new instance open for eMBMS iface and wan iface */ case IPA_WAN_EMBMS_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); /* check for failure return */ if (IPACM_FAILURE == ipa_interface_index) { IPACMERR("IPA_WAN_EMBMS_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); break; } /* change iface category from unknown to EMBMS_IF */ if ((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)) { IPACMDBG(" ODU-mode enable or not (%d) \n",IPACM_Iface::ipacmcfg->ipacm_odu_enable); if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) { IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat=EMBMS_IF; IPACMDBG("WAN eMBMS (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); ifmgr_data.if_index = StaData->if_index; ifmgr_data.if_type = Q6_WAN; create_iface_instance(&ifmgr_data); } else { IPACMDBG("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); } } break; default: break; } return; }
int IPACM_LanToLan::add_offload_link(ipa_ip_type iptype, client_info* client, client_info* peer) { if( (iptype == IPA_IP_v4 && num_offload_pair_v4_ >= MAX_OFFLOAD_PAIR) || (iptype == IPA_IP_v6 && num_offload_pair_v6_ >= MAX_OFFLOAD_PAIR) ) { IPACMDBG_H("The number of offload pairs already reaches maximum.\n"); return IPACM_FAILURE; } if(client == NULL || peer == NULL) { IPACMERR("Either client or peer is NULL.\n"); return IPACM_FAILURE; } uint32_t hdr_hdl, flt_hdl; lan_to_lan_rt_rule_hdl rt_rule_hdl; offload_link_info link_info; if(iptype == IPA_IP_v4) { IPACMDBG_H("Add offload link for IPv4, client IP: 0x%08x, peer IP: 0x%08x \n", client->ip.ipv4_addr, peer->ip.ipv4_addr); } else if(iptype == IPA_IP_v6) { IPACMDBG_H("Add offload link for IPv6, client IP: 0x%08x%08x%08x%08x, peer IP: 0x%08x%08x%08x%08x \n", client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3], peer->ip.ipv6_addr[0], peer->ip.ipv6_addr[1], peer->ip.ipv6_addr[2], peer->ip.ipv6_addr[3]); } else { IPACMERR("IP type is not expected.\n"); return IPACM_FAILURE; } //add lan2lan header if(peer->p_iface->add_lan2lan_hdr(iptype, client->mac_addr, peer->mac_addr, &hdr_hdl) == IPACM_FAILURE) { IPACMERR("Failed to create lan2lan header.\n"); return IPACM_FAILURE; } IPACMDBG_H("Created lan2lan hdr with hdl %d.\n", hdr_hdl); //add lan2lan routing/filtering rules if(peer->p_iface->add_lan2lan_rt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, client->ip.ipv6_addr, peer->ip.ipv6_addr, hdr_hdl, &rt_rule_hdl) == IPACM_FAILURE) { IPACMERR("Failed to create lan2lan rt rule.\n"); goto rt_fail; } IPACMDBG_H("Created %d lan2lan rt rules.\n", rt_rule_hdl.num_rule); IPACMDBG_H("Created lan2lan rt rules with hdl: %d.\n", rt_rule_hdl.rule_hdl[0]); if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, client->ip.ipv6_addr, peer->ip.ipv6_addr, &flt_hdl) == IPACM_FAILURE) { IPACMERR("Failed to create lan2lan flt rule.\n"); goto flt_fail; } IPACMDBG_H("Created lan2lan flt rule with hdl %d.\n", flt_hdl); link_info.peer_pointer = peer; link_info.flt_rule_hdl = flt_hdl; link_info.hdr_hdl = hdr_hdl; memcpy(&link_info.rt_rule_hdl, &rt_rule_hdl, sizeof(lan_to_lan_rt_rule_hdl)); client->link.push_back(link_info); return IPACM_SUCCESS; flt_fail: peer->p_iface->del_lan2lan_rt_rule(iptype, rt_rule_hdl); rt_fail: peer->p_iface->del_lan2lan_hdr(iptype, hdr_hdl); return IPACM_FAILURE; }