HYFI_MC_STATIC unsigned int mc_pre_routing_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int(*okfn)(struct sk_buff *)) { struct hyfi_net_bridge *hyfi_br = hyfi_bridge_get_by_dev(in); struct mc_struct *mc = MC_DEV(hyfi_br); struct ethhdr *eh = eth_hdr(skb); struct net_bridge_port *port; u8 dscp; if (!mc || skb->pkt_type != PACKET_HOST || (port = hyfi_br_port_get(in)) == NULL) goto out; dscp = MC_DSCP(mc->dscp) & (~INET_ECN_MASK); switch (ntohs(skb->protocol)) { case ETH_P_IP: { const struct iphdr *iph = ip_hdr(skb); if (ipv4_is_multicast(iph->daddr) && (!mc->enable_retag || (mc->enable_retag && (ipv4_get_dsfield(iph) == dscp)))) { ip_eth_mc_map(iph->daddr, eh->h_dest); if (mc->debug && printk_ratelimit()) { MC_PRINT("Decap the group "MC_IP4_STR" back to "MC_MAC_STR"\n", MC_IP4_FMT((u8 *)(&iph->daddr)) ,MC_MAC_FMT(eh->h_dest)); } skb->pkt_type = PACKET_MULTICAST; } } break; #ifdef HYBRID_MC_MLD case ETH_P_IPV6: { struct ipv6hdr *iph6 = ipv6_hdr(skb); if (ipv6_addr_is_multicast(&iph6->daddr) && (!mc->enable_retag || (mc->enable_retag && (ipv6_get_dsfield(iph6) == dscp)))) { ipv6_eth_mc_map(&iph6->daddr, eh->h_dest); if (mc->debug && printk_ratelimit()) { MC_PRINT("Decap the group "MC_IP6_STR" back to "MC_MAC_STR"\n", MC_IP6_FMT((__be16 *)(&iph6->daddr)) ,MC_MAC_FMT(eh->h_dest)); } skb->pkt_type = PACKET_MULTICAST; } } break; #endif } out: return NF_ACCEPT; }
int rfc_phase(rfc_pnoder_s *pst_node1, rfc_pnoder_s *pst_node2, rfc_pnoder_s *pst_node3, uint32_t ul_table) { uint32_t i, j, m; uint32_t ul_cell_num, ul_eq_id, ul_cell_index; uint64_t ud_bmp[RFC_SIZE64], *pud_bmp1, *pud_bmp2; rfc_ces_s *pst_ces1, *pst_ces2; rfc_phase_set_s *pst_acl_commit = g_ix_rfc_table_base->pst_acl_commit; rfc_phase_data_s *pst_acl_phase_data = &g_ix_rfc_table_base->st_acl_phase_data; ul_cell_num = pst_node1->ul_eq_id * pst_node2->ul_eq_id; // Initialize phase0_Nodes[com]->listEqs if (rfc_noder_init(pst_acl_commit, pst_acl_phase_data, pst_node3, ul_cell_num) != ACL_OK) { MC_PRINT(" cell alloc failure in table %d, need is %d, free is %d\n", ul_table, ul_cell_num, pst_acl_commit->ul_free_cell_num); return ACL_CELL_ERROR; } // generate phase1_Nodes[com]->listEqs pst_ces1 = &pst_acl_phase_data->st_ces[pst_node1->ul_ces_index]; pst_ces2 = &pst_acl_phase_data->st_ces[pst_node2->ul_ces_index]; ul_cell_index = 0; for (i = 0; i < pst_node1->ul_eq_id; i++) { pud_bmp1 = &pst_acl_phase_data->ud_cbm_data[pst_ces1[i].ul_cbm_index]; for (j = 0; j < pst_node2->ul_eq_id; j++) { pud_bmp2 = &pst_acl_phase_data->ud_cbm_data[pst_ces2[j].ul_cbm_index]; for (m = 0; m < pst_acl_phase_data->u_real_size; m++) ud_bmp[m] = pud_bmp1[m] & pud_bmp2[m]; if ((ul_eq_id = rfc_search_bmp(ud_bmp, ul_table)) == ACL_END_LINK) { MC_PRINT(" EQM ID search failure in table %d\n", ul_table); return ACL_CES_ERROR; } MPP_GET_MDU_VAR(pst_node3->pul_cell) [ul_cell_index++] = ul_eq_id; } } return ACL_OK; }
// Function to fill the table of Phase 2, called by main // return : void int rfc_phase3(rfc_pnoder_s *pst_prev_phase_nodes, rfc_pnoder_s *pst_phase_nodes, uint16_t u_ifgroup) { rfc_pnoder_s *pst_node1, *pst_node2; uint64_t ud_bmp[RFC_SIZE64], *pud_bmp1, *pud_bmp2; uint32_t ul_cell_num, ul_cell_index; uint32_t ul_cost; // cost number with highest priority rfc_ces_s *pst_ces1, *pst_ces2; rfc_phase_set_s *pst_acl_commit = g_ix_rfc_table_base->pst_acl_commit; rfc_phase_data_s *pst_acl_phase_data = &g_ix_rfc_table_base->st_acl_phase_data; rule_comit_t *pst_filter_index = &g_ix_rfc_table_base->commit; uint32_t i, j, m; pst_node1 = &pst_prev_phase_nodes[0]; pst_node2 = &pst_prev_phase_nodes[1]; // alloc memory for Phase2 cell ul_cell_num = pst_node1->ul_eq_id * pst_node2->ul_eq_id; // Initialize phase0_Nodes[com]->listEqs if (rfc_noder_init(pst_acl_commit, pst_acl_phase_data, pst_phase_nodes, ul_cell_num) != ACL_OK) { MC_PRINT(" cell alloc failure in table %u, need is %u, free is %u\n", 12, ul_cell_num, pst_acl_commit->ul_free_cell_num); return ACL_CELL_ERROR; } // generate phase1_Nodes[com]->listEqs pst_ces1 = &pst_acl_phase_data->st_ces[pst_node1->ul_ces_index]; pst_ces2 = &pst_acl_phase_data->st_ces[pst_node2->ul_ces_index]; ul_cell_index = 0; for (i = 0; i < pst_node1->ul_eq_id; i++) { pud_bmp1 = &pst_acl_phase_data->ud_cbm_data[pst_ces1[i].ul_cbm_index]; for (j = 0; j < pst_node2->ul_eq_id; j++) { pud_bmp2 = &pst_acl_phase_data->ud_cbm_data[pst_ces2[j].ul_cbm_index]; for (m = 0; m < pst_acl_phase_data->u_real_size; m++) ud_bmp[m] = pud_bmp1[m] & pud_bmp2[m]; ul_cost = rfc_get_rule_cost(ud_bmp); if (ul_cost == CHUNK_TOTAL_SZIE) pst_phase_nodes->pul_cell_mdu[ul_cell_index++] = CHUNK_TOTAL_SZIE; else pst_phase_nodes->pul_cell_mdu[ul_cell_index++] = pst_filter_index[u_ifgroup].rule_status[ul_cost]; } } return ACL_OK; }
// Function to fill the table of Phase 0 // return : void int rfc_phase0(rfc_phase_set_s *pst_acl_commit, rule_set_t *pst_filter_set, rule_comit_t *pst_filter_index) { uint32_t i = 0; uint32_t n = 0; uint32_t com = 0; uint32_t index = 0;//存放当前chunk中的有效的索引值 uint64_t ud_bmp[RFC_SIZE64]; uint32_t ul_action_num, ul_eq_id; rule_action_t *pst_filter_action[MPP_MAX_PHASE0_CELL] = {NULL}; rule_action_t *pst_action_temp = NULL; rule_action_t st_filter_action[2 * CHUNK_TOTAL_SZIE] = {}; rfc_phase_data_s *pst_acl_phase_data = &g_ix_rfc_table_base->st_acl_phase_data; // Chunk[0] to Chunk[5] of Phase 0 for (com = 0; com < CHUNK_TOTAL_SZIE; com++) { printf("sizeof(pst_filter_action) = %d \n", sizeof(pst_filter_action)); memset (pst_filter_action, 0, sizeof(pst_filter_action)); memset (st_filter_action, 0, sizeof(st_filter_action)); // Initialize ud_bmp = 0 for (i = 0; i < pst_acl_phase_data->u_real_size; i++) ud_bmp[i] = 0; ul_action_num = 0; ul_eq_id = 0; // Initialize phase0_Nodes[com]->listEqs if (rfc_noder_init(pst_acl_commit, pst_acl_phase_data, pst_acl_commit->st_phase_nodes + com, MPP_MAX_PHASE0_CELL) != ACL_OK) { MC_PRINT(" cell alloc failure in table %d, need is %d, free is %d\n", com, MPP_MAX_PHASE0_CELL, pst_acl_commit->ul_free_cell_num); // Phase_Free(); return ACL_CELL_ERROR; } // Pre scan for action //13个chunk都有各自的一个ces表,里面cbm是用链表串起来的长度,单个是64位 for (n = 0; n < pst_filter_index->rule_num; n++) { st_filter_action[ul_action_num].rid = n / LENGTH64; st_filter_action[ul_action_num].action = 1; /**/ DATA64_BITMASK_SET (&st_filter_action[ul_action_num].bitmask, n); index = pst_filter_set->rule[pst_filter_index->rule_status[n]].rule_item[com][0]; st_filter_action[ul_action_num].ck_index = index; st_filter_action[ul_action_num].next = pst_filter_action[index]; /*这里赋值了,就说明这个chunk项的index项不为空*/ pst_filter_action[index] = &st_filter_action[ul_action_num]; ul_action_num++; // second is high+1, the clear bit index = pst_filter_set->rule[pst_filter_index->rule_status[n]].rule_item[com][1] + 1; if (index <= MPP_MAX_PHASE0_CELL) { st_filter_action[ul_action_num].rid = n / LENGTH64; st_filter_action[ul_action_num].action = 0; //st_filter_action[ul_action_num].ud_bitmask = 1 << (n & (LENGTH64 - 1)); DATA64_BITMASK_SET (&st_filter_action[ul_action_num].bitmask, n); st_filter_action[ul_action_num].next = pst_filter_action[index]; st_filter_action[ul_action_num].ck_index = index; pst_filter_action[index] = &st_filter_action[ul_action_num]; ul_action_num++; } } // first the cbm is 0 if (pst_filter_action[0] == NULL) { if ((ul_eq_id = rfc_search_bmp(ud_bmp, com)) == ACL_END_LINK) { MC_PRINT(" EQM ID search failure in table %d\n", com); //Phase_Free(); return ACL_CES_ERROR; } } //预处理表赋值,action为空时候, eq_id为0, 否则填对应的值 for (i = 0; i < MPP_MAX_PHASE0_CELL; i++) { if (pst_filter_action[i] != NULL) { pst_action_temp = pst_filter_action[i]; while (pst_action_temp != NULL) { if (pst_action_temp->action) ud_bmp[pst_action_temp->rid] |= pst_action_temp->bitmask; else ud_bmp[pst_action_temp->rid] &= ~pst_action_temp->bitmask; pst_action_temp = pst_action_temp->next; } if ((ul_eq_id = rfc_search_bmp(ud_bmp, com)) == ACL_END_LINK) { MC_PRINT(" EQM ID search failure in table %d\n", com); return ACL_CES_ERROR; } } pst_acl_commit->st_phase_nodes[com].pul_cell_mdu[i] = ul_eq_id; } for (i = 0; i < ul_action_num; i++) pst_filter_action[st_filter_action[i].ck_index] = NULL; } return ACL_OK; }
// Function to search ud_bmp in listEqs, called by SetPhase0_Cell // call form : SearchBmp(phase0_Nodes[i].listEqs,ud_bmp) // Return: if pud_bmp not exist in listEqs, return -1 // else return eqID of CES whose cbm matches pud_bmp uint32_t rfc_search_bmp(uint64_t *pud_bmp, uint32_t ul_table) { uint32_t i; uint32_t ul_hash_index = 0, ul_index; rfc_phase_data_s *pst_acl_phase_data = &g_ix_rfc_table_base->st_acl_phase_data; uint32_t *pul_hash = pst_acl_phase_data->ul_ces_hash; rfc_ces_s *pst_ces = pst_acl_phase_data->st_ces; rfc_ces_s *ces_tmp; //指向 pst_ces结构体变量 临时变量 uint64_t *cbm_tmp; //指向 pst_acl_phase_data->ud_cbm_data的临时变量 uint32_t ul_same_cbm = ACL_END_LINK; //tCES = ptrlistEqs->head; // get hashindex for (i = 0; i < pst_acl_phase_data->u_real_size; i++) ul_hash_index = (ul_hash_index + pud_bmp[i]) % MPP_MAX_ACL_HASH_SIZE; if (pul_hash[ul_hash_index] != ACL_END_LINK) { ul_index = pul_hash[ul_hash_index]; while (ul_index != ACL_END_LINK) { ces_tmp = &pst_ces[ul_index]; if (ul_same_cbm != ACL_END_LINK) { if (ul_same_cbm == ces_tmp->ul_cbm_index) { if (ces_tmp->ul_table == ul_table) return ces_tmp->ul_eq_id; } } else { // find same ud_bmp from hash table if (rfc_compare_bmp(pud_bmp, &pst_acl_phase_data->ud_cbm_data[ces_tmp->ul_cbm_index], pst_acl_phase_data->u_real_size) == RFCTRUE) { if (ces_tmp->ul_table == ul_table) { return ces_tmp->ul_eq_id; } else { ul_same_cbm = ces_tmp->ul_cbm_index; } } } ul_index = ces_tmp->ul_next; } } if (pst_acl_phase_data->ul_ces_index + 1 >= MPP_MAX_ACL_CES_NUM) { return ACL_END_LINK; } if ((ul_same_cbm == ACL_END_LINK) && (pst_acl_phase_data->ul_cbm_index + pst_acl_phase_data->u_real_size >= MPP_MAX_ACL_CBM_NUM)) { MC_PRINT (" (ul_same_cbm : %d, pst_acl_phase_data->ul_cbm_index : %d, pst_acl_phase_data->u_real_size : %d) &&\n", ul_same_cbm, pst_acl_phase_data->ul_cbm_index, pst_acl_phase_data->u_real_size); return ACL_END_LINK; } ces_tmp = &pst_ces[pst_acl_phase_data->ul_ces_index]; ces_tmp->ul_hash_index = ul_hash_index; ces_tmp->ul_next = pul_hash[ul_hash_index]; ces_tmp->ul_eq_id = g_ix_rfc_table_base->pst_acl_commit->st_phase_nodes[ul_table].ul_eq_id++; ces_tmp->ul_table = ul_table; pul_hash[ul_hash_index] = pst_acl_phase_data->ul_ces_index++; if (ul_same_cbm == ACL_END_LINK) { ces_tmp->ul_cbm_index = pst_acl_phase_data->ul_cbm_index; pst_acl_phase_data->ul_cbm_index += pst_acl_phase_data->u_real_size; cbm_tmp = &pst_acl_phase_data->ud_cbm_data[ces_tmp->ul_cbm_index]; for (i = 0; i < pst_acl_phase_data->u_real_size; i++) cbm_tmp[i] = pud_bmp[i]; } else { ces_tmp->ul_cbm_index = ul_same_cbm; } return ces_tmp->ul_eq_id; }