Exemplo n.º 1
0
/*
 * pnc_mac_da_mask - Add DA MAC address match rule to the MAC section
 * @da: destination MAC address
 * @mask: destination mask
 * @len: destination MAC address length to match on: 0..6
 * @port_mask: source port id: 0..1F or ANY
 * @rxq: rx queue
 * @rinfo: result info bits to set
 */
static struct tcam_entry *pnc_mac_da_mask(unsigned char *da, unsigned char *mask, unsigned int len,
				     unsigned int port_mask, int rxq, unsigned int rinfo)
{
	struct tcam_entry *te = NULL;

	if (len > MV_MAC_ADDR_SIZE)
		goto out;

	if (rinfo >= BIT24)
		goto out;

	te = tcam_sw_alloc(TCAM_LU_MAC);

	/* set match on DA */
	while (len--)
	{
		tcam_sw_set_byte(te, MV_ETH_MH_SIZE + len, da[len]);
		tcam_sw_set_mask(te, MV_ETH_MH_SIZE + len, mask[len]);
	}

	/* port id match */
	tcam_sw_set_port(te, 0, port_mask);

	/* result info bit */
	sram_sw_set_rinfo(te, rinfo);

	/* set rx queue */
    sram_sw_set_rxq(te, rxq, 0);

	/* shift to ethertype */
	sram_sw_set_shift_update(te, 0, MV_ETH_MH_SIZE + 2 * MV_MAC_ADDR_SIZE);
	sram_sw_set_next_lookup(te, TCAM_LU_L2);
out:
	return te;
}
Exemplo n.º 2
0
/*
 * pnc_mcast_all - Accept all MAC multicast of port
 * @port: ingress giga port number.
 * @en: 1 - Accept ALL MCAST, 0 - Discard ALL MCAST
 */
int pnc_mcast_all(unsigned int port, int en)
{
	struct tcam_entry *te;
	unsigned int data, mask;

	te = pnc_tcam_entry_get(TE_MAC_MC_ALL);
	if (te == NULL) {
		mvOsPrintf("%s: MC_ALL entry (tid=%d) is invalid\n", __func__, TE_MAC_MC_ALL);
		return 1;
	}

	/* Update port mask */
	tcam_sw_get_port(te, &data, &mask);
	mask = pnc_port_mask_update(mask, port, en);

	tcam_sw_set_port(te, data, mask);
	tcam_sw_text(te, "mcast_all");

	tcam_hw_write(te, TE_MAC_MC_ALL);
	tcam_sw_free(te);

	return 0;
}
Exemplo n.º 3
0
/*
 * pnc_mac_fc_drop - Add Flow Control MAC address match rule to the MAC section
 * to drop PAUSE frames arriving without Marvell Header on all ports
 */
static void pnc_mac_fc_drop(void)
{
	struct tcam_entry *te = NULL;
	unsigned char da[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 };
	unsigned int len = MV_MAC_ADDR_SIZE;

	te = tcam_sw_alloc(TCAM_LU_MAC);

	/* set match on DA */
	while (len--)
		tcam_sw_set_byte(te, len, da[len]);

	/* port id match */
	tcam_sw_set_port(te, 0, 0);	/* all ports */

	/* result info bit */
	sram_sw_set_rinfo(te, RI_DROP);

	tcam_sw_text(te, "flow control");
	sram_sw_set_lookup_done(te, 1);

	tcam_hw_write(te, TE_MAC_FLOW_CTRL);
	tcam_sw_free(te);
}
Exemplo n.º 4
0
static ssize_t tcam_store(struct device *dev, 
				   struct device_attribute *attr, const char *buf, size_t len)
{
	const char* name = attr->attr.name;
	unsigned int err=0, a=0, b=0;
	unsigned long flags;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	sscanf(buf,"%x %x",&a, &b);

	raw_local_irq_save(flags);

	if (!strcmp(name, "hw_write")) 
		tcam_hw_write(&te, a);
	else if (!strcmp(name, "hw_read")) 
		tcam_hw_read(&te, a);
	else if (!strcmp(name, "hw_debug")) 
		tcam_hw_debug(a);
	else if (!strcmp(name, "hw_inv")) 
		tcam_hw_inv(a);
	else if (!strcmp(name, "hw_inv_all")) 
		tcam_hw_inv_all();
	else if (!strcmp(name, "hw_hits")) 
		tcam_hw_record(a);
#ifdef CONFIG_MV_ETH_PNC_AGING
	else if (!strcmp(name, "age_clear")) 
		mvPncAgingCntrClear(a);
	else if (!strcmp(name, "age_cntr")) {
		b = mvPncAgingCntrRead(a);
		printk("tid=%d: age_cntr = 0x%08x\n", a, b);
	}
#endif /* CONFIG_MV_ETH_PNC_AGING */
	else if (!strcmp(name, "sw_clear")) 
		tcam_sw_clear(&te);
	else if (!strcmp(name, "sw_text")) 
	{
		/* Remove last byte (new line) from the buffer */
		int len = strlen(buf);
		char* temp = mvOsMalloc(len + 1);

		strncpy(temp, buf, len-1);
		temp[len-1] = 0;
		tcam_sw_text(&te, temp);
		mvOsFree(temp);
	}
	else if (!strcmp(name, "t_port"))
		tcam_sw_set_port(&te, a, b);	
	else if (!strcmp(name, "t_lookup")) 
		tcam_sw_set_lookup(&te, a);
	else if (!strcmp(name, "t_ainfo_0")) 
		tcam_sw_set_ainfo(&te, 0<<a, 1<<a);
	else if (!strcmp(name, "t_ainfo_1")) 
		tcam_sw_set_ainfo(&te, 1<<a, 1<<a);
	else if (!strcmp(name, "t_ainfo")) 
		tcam_sw_set_ainfo(&te, a, b);
	else if (!strcmp(name, "t_offset_byte"))
		tcam_sw_set_byte(&te, a, b);
	else if (!strcmp(name, "t_offset_mask"))
		tcam_sw_set_mask(&te, a, b);
	else if (!strcmp(name, "s_lookup")) 
		sram_sw_set_next_lookup(&te, a);
	else if (!strcmp(name, "s_ainfo")) 
		sram_sw_set_ainfo(&te, a, b);
	else if (!strcmp(name, "s_lookup_done"))
		sram_sw_set_lookup_done(&te, a);
	else if (!strcmp(name, "s_next_lookup_shift"))
		sram_sw_set_next_lookup_shift(&te, a);	
	else if (!strcmp(name, "s_rxq")) 
		sram_sw_set_rxq(&te, a, b);
	else if (!strcmp(name, "s_shift_update"))
		sram_sw_set_shift_update(&te,a,b);
	else if (!strcmp(name, "s_rinfo")) 
		sram_sw_set_rinfo(&te, 1 << a);
	else if (!strcmp(name, "s_rinfo_extra")) 
		sram_sw_set_rinfo_extra(&te, a << (b & ~1));
	else if (!strcmp(name, "s_flowid")) 
		sram_sw_set_flowid(&te, a, b);
	else if (!strcmp(name, "s_flowid_nibble")) 
		sram_sw_set_flowid_nibble(&te, a, b);
#ifdef CONFIG_MV_ETH_PNC_AGING
	else if (!strcmp(name, "age_gr_set")) 
		mvPncAgingCntrGroupSet(a, b);
#endif /* CONFIG_MV_ETH_PNC_AGING */
	else {
		err = 1;
		printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
	}
	raw_local_irq_restore(flags);

	if (err) 
		printk("%s: <%s>, error %d\n", __FUNCTION__, attr->attr.name, err);
	
	return err ? -EINVAL : len;
}
Exemplo n.º 5
0
/*
 * pnc_mcast_me - Add DA MAC address of port
 * @mac: Multicast MAC DA or NULL to delete all Multicast DAs for this port
 * @port: ingress giga port number
 */
int pnc_mcast_me(unsigned int port, unsigned char *mac)
{
	struct tcam_entry *te;
	int tid, empty = -1;
	unsigned int data, mask;

	if (mac == NULL) {
		/* Delete all Multicast addresses for this port */
		for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) {
			/* Check TCAM entry */
			te = pnc_tcam_entry_get(tid);
			if (te != NULL) {
				/* delete entry if belong specific port */
				tcam_sw_get_port(te, &data, &mask);
				mask = pnc_port_mask_update(mask, port, 0);
				if (mask == PORT_MASK) {	/* No valid ports */
					tcam_hw_inv(tid);
				} else {
					tcam_sw_set_port(te, data, mask);
					tcam_hw_write(te, tid);
				}
				tcam_sw_free(te);
			}
		}
		return 0;
	}

	/* Add new Multicast DA for this port */
	for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) {
		te = pnc_tcam_entry_get(tid);

		/* Remember first Empty entry */
		if (te == NULL) {
			if (empty == -1)
				empty = tid;

			continue;
		}

		/* Find existing TCAM entry with this DA */
		if (tcam_sw_cmp_bytes(te, MV_ETH_MH_SIZE, MV_MAC_ADDR_SIZE, mac) == 0) {
			/* check and update port mask */
			tcam_sw_get_port(te, &data, &mask);
			mask = pnc_port_mask_update(mask, port, 1);
			tcam_sw_set_port(te, data, mask);

			tcam_hw_write(te, tid);
			tcam_sw_free(te);
			return 0;
		}
		tcam_sw_free(te);
	}

	/* Not found existing entry and no free TCAM entry - Failed */
	if (empty == -1)
		return 1;

	/* Not found existing entry - add to free TCAM entry */
	te = pnc_mac_da(mac, MV_MAC_ADDR_SIZE, pnc_port_mask(port), rxq_mac_mc, RI_DA_MC);
	tcam_sw_text(te, "mcast_me");

	tcam_hw_write(te, empty);
	tcam_sw_free(te);
	return 0;
}