static ssize_t hwf_nfp_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	unsigned int off = 0;
	MV_STATUS status;
	MV_U32 hit;
	MV_NFP_CT_KEY key;
	if (!strcmp(attr->attr.name, "first_get")) {
		status = nfp_ct_first_get(&key, &hit);
	} else if (!strcmp(attr->attr.name, "mostly_get")) {
		status = nfp_ct_mostly_used_get(&key, &hit);
	} else {
		status = nfp_ct_next_get(&key, &hit);
	}
	if (status != MV_OK) {
		off += mvOsSPrintf(buf+off,"No rules found.\n");
		return off;
	}
	if (key.family == AF_INET) {
		off += mvOsSPrintf(buf+off, "\nfamily: IPv4\n");
		off += mvOsSPrintf(buf+off, "sip: "MV_IPQUAD_FMT"\n", MV_IPQUAD(key.src_l3));
		off += mvOsSPrintf(buf+off, "dip: "MV_IPQUAD_FMT"\n", MV_IPQUAD(key.dst_l3));
	} else {
		off += mvOsSPrintf(buf+off, "\nfamily: IPv6\n");
		off += mvOsSPrintf(buf+off, "sip: "MV_IP6_FMT"\n", MV_IP6_ARG(key.src_l3));
		off += mvOsSPrintf(buf+off, "dip: "MV_IP6_FMT"\n", MV_IP6_ARG(key.dst_l3));
	}
	off += mvOsSPrintf(buf+off, "sport: %hu\n", key.sport);
	off += mvOsSPrintf(buf+off, "dport: %hu\n", key.dport);
	off += mvOsSPrintf(buf+off, "proto: %hhu\n\n", key.proto);
	off += mvOsSPrintf(buf+off, "hit counter: %d\n\n", hit);
	return off;
}
int do_ct_age_del_forward(const char *name, int family, unsigned char *sip,
		unsigned char *dip, int sport, int dport, char *protoStr, int mode)
{
	int proto;

	proto = get_protocol_num(protoStr);
	if (!proto)
		return 1;

	NFP_SYSFS_DBG(printk(KERN_INFO "nfp_ct_%s( IPv%d , ", name, family));
	if (family == AF_INET)
		NFP_SYSFS_DBG(printk(MV_IPQUAD_FMT" , "MV_IPQUAD_FMT,
				MV_IPQUAD(sip), MV_IPQUAD(dip)));
	else
		NFP_SYSFS_DBG(printk(MV_IP6_FMT" , "MV_IP6_FMT, MV_IP6_ARG(sip), MV_IP6_ARG(dip)));
	if (!strcmp(name, "forward")) {
		NFP_SYSFS_DBG(printk(KERN_INFO " , %hu , %hu, %d , %d )\n", sport, dport, proto, mode));
		nfp_ct_filter_set(family, sip, dip, sport, dport, proto, mode);
	} else {
		NFP_SYSFS_DBG(printk(KERN_INFO " , %hu , %hu, %d )\n", sport, dport, proto));
		if (!strcmp(name, "del"))
			nfp_ct_del(family, sip, dip, sport, dport, proto);
		else
			printk(KERN_INFO "age: %d\n", nfp_ct_age(family, sip, dip, sport, dport, proto));
	}
	return 0;
}
void print_fib_del_age(int f, unsigned char *sip, unsigned char *dip, char *name)
{
	if (f == AF_INET) {
		printk(KERN_INFO "%s_fib_rule(IPV4 , "MV_IPQUAD_FMT" , "MV_IPQUAD_FMT" )\n", name,
			MV_IPQUAD(sip), MV_IPQUAD(dip));
	} else {
		printk(KERN_INFO "%s_fib_rule(IPV6 , "MV_IP6_FMT" , ", name, MV_IP6_ARG(sip));
		printk(KERN_INFO MV_IP6_FMT")\n", MV_IP6_ARG(dip));
	}
}
/* ip printers */
void print_fib_add(int f, unsigned char *sip, unsigned char *dip, int oif, unsigned char *gtw)
{
	if (f == AF_INET) {
		printk(KERN_INFO "add_fib_rule(IPV4 , "MV_IPQUAD_FMT" , "MV_IPQUAD_FMT" , %d, "MV_IPQUAD_FMT" )\n",
			MV_IPQUAD(sip), MV_IPQUAD(dip), oif, MV_IPQUAD(gtw));
	} else {
		printk(KERN_INFO "add_fib_rule(IPV6 , "MV_IP6_FMT" , ", MV_IP6_ARG(sip));
		printk(KERN_INFO MV_IP6_FMT" , %d , ", MV_IP6_ARG(dip), oif);
		printk(KERN_INFO MV_IP6_FMT" )\n", MV_IP6_ARG(gtw));
	}
}
void print_arp_del_age(int f, unsigned char *gtw, char *name)
{
	if (f == AF_INET)
		printk(KERN_INFO "nfp_arp_%s(IPV4, "MV_IPQUAD_FMT" )\n", name, MV_IPQUAD(gtw));
	else
		printk(KERN_INFO "nfp_arp_%s(IPV6, "MV_IP6_FMT" )\n", name, MV_IP6_ARG(gtw));
}
static ssize_t do_print_local_key(struct device *dev,
				  struct device_attribute *attr, char *buf)
{
	unsigned int off = 0;
	if (!key.init) {
		off += mvOsSPrintf(buf+off, "Print_local_key: local key is not initialized.\n");
		goto key_print_out;
	}
	off += mvOsSPrintf(buf+off, "Local key:\n");
	off += mvOsSPrintf(buf+off, "    family: IPv4\n");
	off += mvOsSPrintf(buf+off, "    sip: "MV_IPQUAD_FMT"\n", MV_IPQUAD(key.sip));
	off += mvOsSPrintf(buf+off, "    dip: "MV_IPQUAD_FMT"\n", MV_IPQUAD(key.dip));
	off += mvOsSPrintf(buf+off, "    sport: %hu\n", key.sport);
	off += mvOsSPrintf(buf+off, "    dport: %hu\n", key.dport);
	off += mvOsSPrintf(buf+off, "    proto: %hhu\n\n", key.proto);
key_print_out:
	return off;
}
void print_arp_add(int f, unsigned char *gtw, MV_U8 *mac)
{
	if (f == AF_INET) {
		printk(KERN_INFO "nfp_arp_add(IPV4, "MV_IPQUAD_FMT" , "MV_MACQUAD_FMT" )\n",
			MV_IPQUAD(gtw), MV_MACQUAD(mac));
	} else {
		printk(KERN_INFO "nfp_arp_add(IPV6, "MV_IP6_FMT" , "MV_MACQUAD_FMT" )\n",
			MV_IP6_ARG(gtw), MV_MACQUAD(mac));
	}
}
Exemple #8
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;
}
static void mvNfpFibRulePrint(NFP_RULE_FIB *fib)
{
	if (fib->family == MV_INET) {

		mvOsPrintf("IPv4: " MV_IPQUAD_FMT "->" MV_IPQUAD_FMT"\n",
			   MV_IPQUAD(*((u32 *) fib->srcL3)), MV_IPQUAD(*((u32 *) fib->dstL3)));
	} else {
		mvOsPrintf("IPv6: " MV_IP6_FMT "->" MV_IP6_FMT"\n",
					MV_IP6_ARG(fib->srcL3), MV_IP6_ARG(fib->dstL3));

	}
	mvOsPrintf("     mh=%2.2x:%2.2x da=" MV_MACQUAD_FMT " sa=" MV_MACQUAD_FMT "\n",
				((MV_U8 *) &fib->mh)[0], ((MV_U8 *) &fib->mh)[1], MV_MACQUAD(fib->da), MV_MACQUAD(fib->sa));
	mvOsPrintf("     outport=%d, outdev=%p, flags=0x%x, ref=%d, age=%x, fib=%p, pnc=%p\n",
				fib->outport, fib->outdev, fib->flags, fib->ref, fib->age, fib, fib->pnc);

	mvOsPrintf("     Flags: ");
	if (fib->flags & NFP_F_DYNAMIC)
		mvOsPrintf("NFP_F_DYNAMIC ");
	if (fib->flags & NFP_F_STATIC)
		mvOsPrintf("NFP_F_STATIC ");
	if (fib->flags & NFP_F_INV)
		mvOsPrintf("NFP_F_INV ");
	if (fib->flags & NFP_F_SNAT)
		mvOsPrintf("NFP_F_SNAT ");
	if (fib->flags & NFP_F_DNAT)
		mvOsPrintf("NFP_F_DNAT ");
	if (fib->flags & NFP_F_BUSY)
		mvOsPrintf("NFP_F_BUSY ");
	if (fib->flags & NFP_F_PPPOE_ADD)
		mvOsPrintf("NFP_F_PPPOE_ADD ");
	if (fib->flags & NFP_F_PPPOE_REMOVE)
		mvOsPrintf("NFP_F_PPPOE_REMOVE ");
	if (fib->flags & NFP_F_HWF)
		mvOsPrintf("NFP_F_HWF ");
	if (fib->flags & NFP_F_BRIDGE)
		mvOsPrintf("NFP_F_BRIDGE ");

	mvOsPrintf("\n");
}
Exemple #10
0
void l2fw_dump(void)
{
    MV_U32 i = 0;
    L2FW_RULE *currRule;
    MV_U8	  *srcIP, *dstIP;

    mvOsPrintf("\nPrinting L2fw Rule Database: \n");
    mvOsPrintf("*******************************\n");

    for (i = 0; i < L2FW_HASH_SIZE; i++) {
        currRule = l2fw_hash[i];
        srcIP = (MV_U8 *)&(currRule->srcIP);
        dstIP = (MV_U8 *)&(currRule->dstIP);

        while (currRule != NULL) {
            mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u    out port=%d (hash=%x)\n",
                       MV_IPQUAD(srcIP), MV_IPQUAD(dstIP),
                       currRule->port, i);
            currRule = currRule->next;
        }
    }

}
int do_ct_tbf(const char *name, int family, unsigned char *sip,
		unsigned char *dip, int sport, int dport, char *protoStr, int tbfIndex)
{
	int proto;
	proto = get_protocol_num(protoStr);
	if (!proto)
		return 1;

	NFP_SYSFS_DBG(printk(KERN_INFO "nfp_ct_%s( IPv%d , ", name, family));
	if (family == AF_INET)
		NFP_SYSFS_DBG(printk(KERN_INFO MV_IPQUAD_FMT" , "MV_IPQUAD_FMT,
				MV_IPQUAD(sip), MV_IPQUAD(dip)));
	else
		NFP_SYSFS_DBG(printk(KERN_INFO MV_IP6_FMT" , "MV_IP6_FMT, MV_IP6_ARG(sip), MV_IP6_ARG(dip)));
	if (!strcmp(name, "rate_limit_set")) {
		NFP_SYSFS_DBG(printk(KERN_INFO " , %hu , %hu, %d , %d )\n", sport, dport, proto, tbfIndex));
		nfp_ct_rate_limit_set(family, sip, dip, sport, dport, proto, tbfIndex);
	} else {
		NFP_SYSFS_DBG(printk(KERN_INFO " , %hu , %hu, %d )\n", sport, dport, proto));
		nfp_ct_rate_limit_del(family, sip, dip, sport, dport, proto);
	}
	return 0;
}
	mvOsMemset(nat_hash, 0, bytes);

	mvOsPrintf("NFP (nat) init %d entries, %d bytes\n", NFP_NAT_HASH_SIZE, bytes);

	return MV_OK;
}

static MV_VOID mvNfpNatRulePrint(NFP_RULE_NAT *nat)
{
	mvOsPrintf(MV_IPQUAD_FMT":%d"
				"->"MV_IPQUAD_FMT":%d"
				" %-2d "
				"%s:"MV_IPQUAD_FMT" "
				"age=%x (%p)\n",
				MV_IPQUAD(nat->sip), MV_16BIT_BE(nat->ports & 0xFFFF),
				MV_IPQUAD(nat->dip), MV_16BIT_BE(nat->ports >> 16),
				nat->proto, nat->flags & NFP_F_DNAT ? "DNAT" : "SNAT",
				MV_IPQUAD(nat->nip), nat->age, nat);
}

static INLINE MV_U32 mvNfpNatHash(NFP_RULE_NAT *nat)
{
	int family = MV_INET;
	return mv_jhash_2addr(family, (const MV_U8 *)&nat->sip, (const MV_U8 *)&nat->dip,
					nat->ports | nat->proto, mgr_rule_jhash_iv);

}

static INLINE NFP_RULE_NAT *mvNfpNatLookup(NFP_RULE_NAT *nat2)
{
Exemple #13
0
static inline int mv_eth_l2fw_rx(struct eth_port *pp, int rx_todo, int rxq)
{
    struct eth_port  *new_pp;
    L2FW_RULE *l2fw_rule;
    MV_NETA_RXQ_CTRL *rx_ctrl = pp->rxq_ctrl[rxq].q;
    int rx_done, rx_filled;
    struct neta_rx_desc *rx_desc;
    u32 rx_status = MV_OK;
    struct eth_pbuf *pkt;
    struct eth_pbuf *newpkt = NULL;
    struct bm_pool *pool;
    MV_STATUS status = MV_OK;
    struct eth_port_l2fw *ppl2fw = mv_eth_ports_l2fw[pp->port];
    MV_IP_HEADER *pIph = NULL;
    MV_U8 *pData;
    int	ipOffset;

    rx_done = mvNetaRxqBusyDescNumGet(pp->port, rxq);
    mvOsCacheIoSync();
    if (rx_todo > rx_done)
        rx_todo = rx_done;
    rx_done = 0;
    rx_filled = 0;

    /* Fairness NAPI loop */
    while (rx_done < rx_todo) {
#ifdef CONFIG_MV_ETH_RX_DESC_PREFETCH
        rx_desc = mv_eth_rx_prefetch(pp, rx_ctrl, rx_done, rx_todo);
        if (!rx_desc)
            printk(KERN_INFO "rx_desc is NULL in %s\n", __func__);
#else
        rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
        mvOsCacheLineInv(NULL, rx_desc);
        prefetch(rx_desc);
#endif /* CONFIG_MV_ETH_RX_DESC_PREFETCH */

        rx_done++;
        rx_filled++;

        pkt = (struct eth_pbuf *)rx_desc->bufCookie;
        if (!pkt) {
            printk(KERN_INFO "pkt is NULL in ; rx_done=%d %s\n", rx_done, __func__);
            return rx_done;
        }

        pool = &mv_eth_pool[pkt->pool];
        rx_status = rx_desc->status;
        if (((rx_status & NETA_RX_FL_DESC_MASK) != NETA_RX_FL_DESC_MASK) ||
                (rx_status & NETA_RX_ES_MASK)) {
            STAT_ERR(pp->stats.rx_error++);

            if (pp->dev)
                pp->dev->stats.rx_errors++;

            mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
            continue;
        }

        pkt->bytes = rx_desc->dataSize - (MV_ETH_CRC_SIZE + MV_ETH_MH_SIZE);

        pData = pkt->pBuf + pkt->offset;

#ifdef CONFIG_MV_ETH_PNC
        ipOffset = NETA_RX_GET_IPHDR_OFFSET(rx_desc);
#else
        if ((rx_desc->status & ETH_RX_VLAN_TAGGED_FRAME_MASK))
            ipOffset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN;
        else
            ipOffset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER);
#endif

        pIph = (MV_IP_HEADER *)(pData + ipOffset);
        if (pIph == NULL) {
            printk(KERN_INFO "pIph==NULL in %s\n", __func__);
            continue;
        }
#ifdef CONFIG_MV_ETH_L2FW_DEBUG
        if (pIph) {
            MV_U8 *srcIP, *dstIP;
            srcIP = (MV_U8 *)&(pIph->srcIP);
            dstIP = (MV_U8 *)&(pIph->dstIP);
            printk(KERN_INFO "%u.%u.%u.%u->%u.%u.%u.%u in %s\n", MV_IPQUAD(srcIP), MV_IPQUAD(dstIP), __func__);
        } else
            printk(KERN_INFO "pIph is NULL in %s\n", __func__);
#endif
        if (espEnabled)
            new_pp  = mv_eth_ports[ppl2fw->txPort];
        else {
            l2fw_rule = l2fw_lookup(pIph->srcIP, pIph->dstIP);

            if (!l2fw_rule) {
#ifdef CONFIG_MV_ETH_L2FW_DEBUG
                printk(KERN_INFO "l2fw_lookup() failed in %s\n", __func__);
#endif
                mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
                continue;
            }

#ifdef CONFIG_MV_ETH_L2FW_DEBUG
            printk(KERN_INFO "l2fw_lookup() is ok l2fw_rule->port=%d in %s\n", l2fw_rule->port, __func__);
#endif
            new_pp  = mv_eth_ports[l2fw_rule->port];
        }

        switch (ppl2fw->cmd) {
        case TX_AS_IS:
#ifdef CONFIG_MV_ETH_L2SEC
            if (espEnabled) {
                status = handleEsp(pkt, rx_desc, new_pp, pp->port);
            }
            else
#endif
                status = mv_eth_l2fw_tx(pkt, new_pp, 0, rx_desc);
            break;

        case SWAP_MAC:
            mvOsCacheLineInv(NULL, pkt->pBuf + pkt->offset);
            l2fw_swap_mac(pkt);
            mvOsCacheLineFlush(NULL, pkt->pBuf+pkt->offset);
            status = mv_eth_l2fw_tx(pkt, new_pp, 0, rx_desc);
            break;

        case COPY_AND_SWAP:
            if (pkt->bytes >= l2fw_xor_threshold) {
                newpkt = eth_l2fw_copy_packet_withXor(pkt);
                if (newpkt)
                    status = mv_eth_l2fw_tx(newpkt, new_pp, 1, rx_desc);
                else
                    status = MV_ERROR;
            } else {
                newpkt = eth_l2fw_copy_packet_withoutXor(pkt);
                if (newpkt)
                    status = mv_eth_l2fw_tx(newpkt, new_pp, 0, rx_desc);
                else
                    status = MV_ERROR;
            }
        }
        if (status == MV_OK) {
            mvOsCacheLineInv(NULL, rx_desc);
            /* we do not need the pkt , we do not do anything with it*/
            if  ((ppl2fw->cmd	== COPY_AND_SWAP) && !(espEnabled))
                mv_eth_pool_put(pool, pkt);
            continue;
        } else if (status == MV_DROPPED) {
            mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
            if ((ppl2fw->cmd	== COPY_AND_SWAP) && !(espEnabled))
                mv_eth_pool_put(pool, newpkt);

            continue;
        } else if (status == MV_ERROR) {
            printk(KERN_INFO "MV_ERROR in %s\n", __func__);
            mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
        }

    } /* of while */
    /* Update RxQ management counters */
    mvOsCacheIoSync();

    mvNetaRxqDescNumUpdate(pp->port, rxq, rx_done, rx_filled);

    return rx_done;
}
Exemple #14
0
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;

}