/* Get the count value for a NAT rule */ MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto) { MV_U32 hash, hash_tr; MV_FP_NAT_RULE *pNatRule; hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)((dstPort << 16) | srcPort), (MV_U32)((fp_ip_jhash_iv << 8) | proto)); hash_tr = hash & (natRuleDbSize - 1); pNatRule = natRuleDb[hash_tr].natRuleChain; while(pNatRule) { /* look for a matching rule */ if( (pNatRule->dstIp == dstIp) && (pNatRule->srcIp == srcIp) && (pNatRule->proto == proto) && (pNatRule->dstPort == dstPort) && (pNatRule->srcPort == srcPort) ) { return pNatRule->new_count; } pNatRule = pNatRule->next; } return 0; }
MV_STATUS mvFpToSSet(MV_FP_RULE *pSetRule) { MV_U32 hash, hash_tr; MV_FP_RULE *pRule; hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); pRule = ruleDb[hash_tr].ruleChain; while (pRule) { if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp && pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) { pRule->routingInfo.txq = pSetRule->routingInfo.txq; pRule->routingInfo.dscp = pSetRule->routingInfo.dscp; nfpRuleUpdateCount++; #ifdef MV_FP_DEBUG mvOsPrintf("ToSNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x TOS=0x%x TxQ=%d\n", nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pRule->routingInfo.dscp, pRule->routingInfo.txq); #endif return MV_OK; } pRule = pRule->next; } return MV_NOT_FOUND; }
/* Delete a specified rule from the Routing + ARP information table */ MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule) { MV_U32 hash, hash_tr; MV_FP_RULE *currRule, *prevRule; nfpRuleDeleteCount++; hash = mv_jhash_3words(rule->routingInfo.dstIp, rule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); prevRule = NULL; for (currRule = ruleDb[hash_tr].ruleChain; currRule != NULL; prevRule = currRule, currRule = currRule->next) { if ((currRule->routingInfo.srcIp == rule->routingInfo.srcIp) && (currRule->routingInfo.dstIp == rule->routingInfo.dstIp)) { if (prevRule == NULL) ruleDb[hash_tr].ruleChain = currRule->next; else prevRule->next = currRule->next; #ifdef MV_FP_DEBUG mvOsPrintf("DelNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n", nfpRuleDeleteCount, MV_IP_QUAD(currRule->routingInfo.dstIp), MV_IP_QUAD(currRule->routingInfo.srcIp), hash_tr); #endif mvOsFree(currRule); return MV_OK; } } return MV_NOT_FOUND; }
MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule) { MV_U32 hash, hash_tr; MV_FP_RULE *pRule; hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); pRule = ruleDb[hash_tr].ruleChain; while (pRule) { if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp) && (pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) { pRule->routingInfo.aware_flags = pSetRule->routingInfo.aware_flags; #ifdef MV_FP_DEBUG mvOsPrintf("Update FP aware: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash0x%x, flags=0x%x\n", MV_IP_QUAD(pSetRule->routingInfo.dstIp), MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags); #endif return MV_OK; } pRule = pRule->next; } #ifdef MV_FP_DEBUG mvOsPrintf("FP aware NOT found: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%x, flags=0x%x\n", MV_IP_QUAD(pSetRule->routingInfo.dstIp), MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags); #endif return MV_NOT_FOUND; }
/* Find and return the first matching rule in the Routing + ARP information table */ static INLINE MV_FP_RULE* mvFpRuleFind(MV_U32 dstIp, MV_U32 srcIp) { MV_U32 hash, hash_tr; MV_FP_RULE* pRule; int count = 0; hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); pRule = ruleDb[hash_tr].ruleChain; while(pRule) { /* look for a matching rule */ if( (pRule->routingInfo.dstIp == dstIp) && (pRule->routingInfo.srcIp == srcIp) ) { pRule->mgmtInfo.new_count++; return pRule; } pRule = pRule->next; count++; } return NULL; }
/* in the Routing + ARP information table */ MV_STATUS mvFpRuleSet(MV_FP_RULE *pSetRule) { MV_U32 hash, hash_tr; int depth = 0; MV_FP_RULE *pRule, *pNewRule; hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); pRule = ruleDb[hash_tr].ruleChain; while (pRule) { if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp && pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) { mvFpRuleCopy(pRule, pSetRule); nfpRuleUpdateCount++; #ifdef MV_FP_DEBUG mvOsPrintf("UpdNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x TOS=0x%x TxQ=%d\n", nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pRule->routingInfo.dscp, pRule->routingInfo.txq); #endif return MV_OK; } pRule = pRule->next; } /* Allocate new entry */ pNewRule = mvOsMalloc(sizeof(MV_FP_RULE)); if (pNewRule == NULL) { mvOsPrintf("mvFpRuleSet: Can't allocate new rule\n"); return MV_FAIL; } mvFpRuleCopy(pNewRule, pSetRule); pNewRule->next = NULL; if (ruleDb[hash_tr].ruleChain == NULL) ruleDb[hash_tr].ruleChain = pNewRule; else { pRule = ruleDb[hash_tr].ruleChain; while (pRule->next != NULL) { depth++; pRule = pRule->next; } pRule->next = pNewRule; } if (depth > nfpHashMaxDepth) nfpHashMaxDepth = depth; nfpRuleSetCount++; #ifdef MV_FP_DEBUG mvOsPrintf("SetNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x, aware=0x%02x\n", nfpRuleSetCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags); #endif return MV_OK; }
static MV_FP_FDB_RULE* mvFpFdbLookup(MV_U32 ifIndex, MV_U8* pDA) { MV_U32 hash, hash_tr; MV_FP_FDB_RULE* pRule; MV_U32 bridgeId; int count = 0; if (ifIndex >= ETH_FP_IFINDEX_MAX) return NULL; if (!(bridgeId = fdbMember[ifIndex])) return NULL; hash = mv_jhash_3words(bridgeId, 0, *(MV_U32*)(pDA+2), fp_ip_jhash_iv); hash_tr = hash & (fdbRuleDbSize - 1); pRule = fdbRuleDb[hash_tr].ruleChain; while (pRule) { /* MV_NFP_DBG("%s: looking %d %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, bridgeId, pRule->fdbInfo.mac[0], pRule->fdbInfo.mac[1], pRule->fdbInfo.mac[2], pRule->fdbInfo.mac[3], pRule->fdbInfo.mac[4], pRule->fdbInfo.mac[5]); */ if ((bridgeId == pRule->fdbInfo.bridge) && (*((MV_U16*)(pDA+0)) == *(MV_U16*)(&pRule->fdbInfo.mac[0])) && (*((MV_U16*)(pDA+2)) == *(MV_U16*)(&pRule->fdbInfo.mac[2])) && (*((MV_U16*)(pDA+4)) == *(MV_U16*)(&pRule->fdbInfo.mac[4]))) { pRule->mgmtInfo.new_count++; break; } pRule = pRule->next; count++; } /* if (pRule) MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => if=%d flags=%x\n", __FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5], pRule->fdbInfo.ifIndex, pRule->fdbInfo.flags); else MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => unknown\n", __FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5]); */ return pRule; }
/* Get the count value for a rule that matches the given SIP, DIP */ MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp) { MV_U32 hash, hash_tr; MV_FP_RULE *pRule; hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) 0, fp_ip_jhash_iv); hash_tr = hash & (ruleDbSize - 1); pRule = ruleDb[hash_tr].ruleChain; while (pRule) { /* look for a matching rule */ if ((pRule->routingInfo.dstIp == dstIp) && (pRule->routingInfo.srcIp == srcIp)) return pRule->mgmtInfo.new_count; pRule = pRule->next; } return 0; }
MV_STATUS l2fw_add(MV_U32 srcIP, MV_U32 dstIP, int port) { L2FW_RULE *l2fw_rule; MV_U8 *srcIPchr, *dstIPchr; MV_U32 hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv); hash &= L2FW_HASH_MASK; if (numHashEntries == L2FW_HASH_SIZE) { printk(KERN_INFO "cannot add entry, hash table is full, there are %d entires \n", L2FW_HASH_SIZE); return MV_ERROR; } srcIPchr = (MV_U8 *)&(srcIP); dstIPchr = (MV_U8 *)&(dstIP); #ifdef CONFIG_MV_ETH_L2FW_DEBUG mvOsPrintf("srcIP=%x dstIP=%x in %s\n", srcIP, dstIP, __func__); mvOsPrintf("srcIp = %u.%u.%u.%u in %s\n", MV_IPQUAD(srcIPchr), __func__); mvOsPrintf("dstIp = %u.%u.%u.%u in %s\n", MV_IPQUAD(dstIPchr), __func__); #endif l2fw_rule = l2fw_lookup(srcIP, dstIP); if (l2fw_rule) return MV_OK; l2fw_rule = (L2FW_RULE *)mvOsMalloc(sizeof(L2FW_RULE)); if (!l2fw_rule) { mvOsPrintf("%s: OOM\n", __func__); return MV_FAIL; } #ifdef CONFIG_MV_ETH_L2FW_DEBUG mvOsPrintf("adding a rule to l2fw hash in %s\n", __func__); #endif l2fw_rule->srcIP = srcIP; l2fw_rule->dstIP = dstIP; l2fw_rule->port = port; l2fw_rule->next = l2fw_hash[hash]; l2fw_hash[hash] = l2fw_rule; numHashEntries++; return MV_OK; }
/* Delete a specified NAT rule from the SNAT + DNAT table */ MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule) { MV_U32 hash, hash_tr; MV_FP_NAT_RULE *currRule, *prevRule; natRuleDeleteCount++; hash = mv_jhash_3words(natRule->dstIp, natRule->srcIp, (MV_U32)((natRule->dstPort << 16) | natRule->srcPort), (MV_U32)((fp_ip_jhash_iv << 8) | natRule->proto)); hash_tr = hash & (natRuleDbSize - 1); prevRule = NULL; for (currRule = natRuleDb[hash_tr].natRuleChain; currRule != NULL; prevRule = currRule, currRule = currRule->next) { if (currRule->srcIp == natRule->srcIp && currRule->dstIp == natRule->dstIp && currRule->srcPort == natRule->srcPort && currRule->dstPort == natRule->dstPort && currRule->proto == natRule->proto ) { if (prevRule == NULL) natRuleDb[hash_tr].natRuleChain = currRule->next; else prevRule->next = currRule->next; #ifdef MV_FP_DEBUG mvOsPrintf("DelNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x\n", natRuleDeleteCount, currRule->dstIp, currRule->srcIp, currRule->proto, MV_16BIT_BE(currRule->dstPort), MV_16BIT_BE(currRule->srcPort), hash_tr); #endif mvOsFree(currRule); return MV_OK; } } return MV_NOT_FOUND; }
static L2FW_RULE *l2fw_lookup(MV_U32 srcIP, MV_U32 dstIP) { MV_U32 hash; L2FW_RULE *rule; hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv); hash &= L2FW_HASH_MASK; rule = l2fw_hash[hash]; #ifdef CONFIG_MV_ETH_L2FW_DEBUG if (rule) printk(KERN_INFO "rule is not NULL in %s\n", __func__); else printk(KERN_INFO "rule is NULL in %s\n", __func__); #endif while (rule) { if ((rule->srcIP == srcIP) && (rule->dstIP == dstIP)) return rule; rule = rule->next; } return NULL; }
/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */ MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *pSetRule) { int depth = 0; MV_U32 hash, hash_tr; MV_FP_NAT_RULE *pNatRule, *pNewRule; hash = mv_jhash_3words(pSetRule->dstIp, pSetRule->srcIp, (MV_U32)((pSetRule->dstPort << 16) | pSetRule->srcPort), (MV_U32)((fp_ip_jhash_iv << 8) | pSetRule->proto)); hash_tr = hash & (natRuleDbSize - 1); pNatRule = natRuleDb[hash_tr].natRuleChain; while(pNatRule) { /* look for a matching rule */ if( (pNatRule->dstIp == pSetRule->dstIp) && (pNatRule->srcIp == pSetRule->srcIp) && (pNatRule->proto == pSetRule->proto) && (pNatRule->dstPort == pSetRule->dstPort) && (pNatRule->srcPort == pSetRule->srcPort) ) { /* update rule */ mvFpNatRuleUpdate(pNatRule, pSetRule); natRuleUpdateCount++; #ifdef MV_FP_DEBUG mvOsPrintf("UpdNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", natRuleUpdateCount, pNatRule->dstIp, pNatRule->srcIp, pNatRule->proto, MV_16BIT_BE(pNatRule->dstPort), MV_16BIT_BE(pNatRule->srcPort), hash_tr, pNatRule->flags); #endif return MV_OK; } pNatRule = pNatRule->next; } /* Allocate new entry */ pNewRule = mvOsMalloc(sizeof(MV_FP_NAT_RULE)); if(pNewRule == NULL) { mvOsPrintf("mvFpNatRuleSet: Can't allocate new rule\n"); return MV_FAIL; } memcpy(pNewRule, pSetRule, sizeof(*pNewRule)); pNewRule->next = NULL; if(natRuleDb[hash_tr].natRuleChain == NULL) { natRuleDb[hash_tr].natRuleChain = pNewRule; } else { pNatRule = natRuleDb[hash_tr].natRuleChain; while (pNatRule->next != NULL) { depth++; pNatRule = pNatRule->next; } pNatRule->next = pNewRule; } if(depth > natHashMaxDepth) natHashMaxDepth = depth; natRuleSetCount++; #ifdef MV_FP_DEBUG mvOsPrintf("SetNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", natRuleSetCount, pNewRule->dstIp, pNewRule->srcIp, pNewRule->proto, MV_16BIT_BE(pNewRule->dstPort), MV_16BIT_BE(pNewRule->srcPort), hash_tr, pNewRule->flags); #endif return MV_OK; }
MV_STATUS l2fw_add_ip(const char *buf) { char *addr1, *addr2; L2FW_RULE *l2fw_rule; MV_U32 srcIP; MV_U32 dstIP; MV_U8 *srcIPchr, *dstIPchr; char dest1[15]; char dest2[15]; char *portStr; int offset1, offset2, port; MV_U32 hash = 0; if (numHashEntries == L2FW_HASH_SIZE) { printk(KERN_INFO "cannot add entry, hash table is full, there are %d entires \n", L2FW_HASH_SIZE); return MV_ERROR; } memset(dest1, 0, sizeof(dest1)); memset(dest2, 0, sizeof(dest2)); addr1 = strchr(buf, ','); addr2 = strchr(addr1+1, ','); offset1 = addr1-buf; offset2 = addr2-addr1; if (!addr1) { printk(KERN_INFO "first separating comma (',') missing in input in %s\n", __func__); return MV_FAIL; } if (!addr2) { printk(KERN_INFO "second separating comma (',') missing in input in %s\n", __func__); return MV_FAIL; } strncpy(dest1, buf, addr1-buf); srcIP = in_aton(dest1); strncpy(dest2, buf+offset1+1, addr2-addr1-1); dstIP = in_aton(dest2); srcIPchr = (MV_U8 *)&(srcIP); dstIPchr = (MV_U8 *)&(dstIP); portStr = addr2+1; if (*portStr == 'D') { L2FW_RULE *l2fw_rule_to_del, *prev; hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv); hash &= L2FW_HASH_MASK; l2fw_rule_to_del = l2fw_hash[hash]; prev = NULL; while (l2fw_rule_to_del) { if ((l2fw_rule_to_del->srcIP == srcIP) && (l2fw_rule_to_del->dstIP == dstIP)) { if (prev) prev->next = l2fw_rule_to_del->next; else l2fw_hash[hash] = l2fw_rule_to_del->next; mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u deleted\n", MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr)); mvOsFree(l2fw_rule_to_del); numHashEntries--; return MV_OK; } prev = l2fw_rule_to_del; l2fw_rule_to_del = l2fw_rule_to_del->next; } mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u : entry not found\n", MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr)); return MV_NOT_FOUND; } port = atoi(portStr); hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv); hash &= L2FW_HASH_MASK; l2fw_rule = l2fw_lookup(srcIP, dstIP); if (l2fw_rule) { mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u : entry already exist\n", MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr)); return MV_OK; } l2fw_rule = (L2FW_RULE *)mvOsMalloc(sizeof(L2FW_RULE)); if (!l2fw_rule) { mvOsPrintf("%s: OOM\n", __func__); return MV_FAIL; } #ifdef CONFIG_MV_ETH_L2FW_DEBUG mvOsPrintf("adding a rule to l2fw hash in %s\n", __func__); #endif l2fw_rule->srcIP = srcIP; l2fw_rule->dstIP = dstIP; l2fw_rule->port = port; l2fw_rule->next = l2fw_hash[hash]; l2fw_hash[hash] = l2fw_rule; numHashEntries++; return MV_OK; }
static INLINE MV_U32 mvFpFdbRuleHash(MV_FP_FDB_RULE *rule) { return mv_jhash_3words( rule->fdbInfo.bridge, 0,*(MV_U32*)(rule->fdbInfo.mac+2), fp_ip_jhash_iv); }