momo zone

调核人的blog

Monthly Archives: 九月 2015

marvell的Yukon-2网卡的小问题

硬件信息:
Yukon-2 EC Ultra chip revision 2
02:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8056 PCI-E Gigabit Ethernet Controller (rev 12)
驱动是sky2

把MTU设置为很小的值后会出现error:
[15922.211053] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15922.211064] sky2 0000:02:00.0 enp2s0: rx error, status 0x1e40100 length 320
[15922.512083] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15923.112009] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15924.315657] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15926.709683] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15928.762871] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15928.762882] sky2 0000:02:00.0 enp2s0: rx error, status 0x1e40100 length 320
[15929.064820] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15929.661903] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15930.861499] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15931.513735] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15933.261882] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[15938.064230] sky2 0000:02:00.0 enp2s0: rx error, status 0x24e0100 length 318
[16017.611463] sky2 0000:02:00.0 enp2s0: rx error, status 0x1ab0100 length 319

看了下代码确实是mtu过小,收到了超长包导致的问题,不过包还是收了。
drivers/net/ethernet/marvell/sky2.c

static struct sk_buff *sky2_receive(struct net_device *dev,
				    u16 length, u32 status)
{
 	struct sky2_port *sky2 = netdev_priv(dev);
	struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
	struct sk_buff *skb = NULL;
	u16 count = (status & GMR_FS_LEN) >> 16;

	netif_printk(sky2, rx_status, KERN_DEBUG, dev,
		     "rx slot %u status 0x%x len %d\n",
		     sky2->rx_next, status, length);

	sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
	prefetch(sky2->rx_ring + sky2->rx_next);

	if (vlan_tx_tag_present(re->skb))
		count -= VLAN_HLEN;	/* Account for vlan tag */

	/* This chip has hardware problems that generates bogus status.
	 * So do only marginal checking and expect higher level protocols
	 * to handle crap frames.
	 */
	if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
	    sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 &&
	    length != count)
		goto okay;

	if (status & GMR_FS_ANY_ERR)
		goto error;

	if (!(status & GMR_FS_RX_OK))
		goto resubmit;

	/* if length reported by DMA does not match PHY, packet was truncated */
	if (length != count)
		goto error;

okay:
	if (needs_copy(re, length))
		skb = receive_copy(sky2, re, length);
	else
		skb = receive_new(sky2, re, length);

	dev->stats.rx_dropped += (skb == NULL);

resubmit:
	sky2_rx_submit(sky2, re);

	return skb;

error:
	++dev->stats.rx_errors;

	if (net_ratelimit())
		netif_info(sky2, rx_err, dev,
			   "rx error, status 0x%x length %d\n", status, length);

	goto resubmit;
}

drivers/net/ethernet/marvell/sky2.h

enum {
	GMR_FS_LEN	= 0x7fff<<16, /* Bit 30..16:	Rx Frame Length */
	GMR_FS_VLAN	= 1<<13, /* VLAN Packet */
	GMR_FS_JABBER	= 1<<12, /* Jabber Packet */
	GMR_FS_UN_SIZE	= 1<<11, /* Undersize Packet */
	GMR_FS_MC	= 1<<10, /* Multicast Packet */
	GMR_FS_BC	= 1<<9,  /* Broadcast Packet */
	GMR_FS_RX_OK	= 1<<8,  /* Receive OK (Good Packet) */
	GMR_FS_GOOD_FC	= 1<<7,  /* Good Flow-Control Packet */
	GMR_FS_BAD_FC	= 1<<6,  /* Bad  Flow-Control Packet */
	GMR_FS_MII_ERR	= 1<<5,  /* MII Error */
	GMR_FS_LONG_ERR	= 1<<4,  /* Too Long Packet */
	GMR_FS_FRAGMENT	= 1<<3,  /* Fragment */

	GMR_FS_CRC_ERR	= 1<<1,  /* CRC Error */
	GMR_FS_RX_FF_OV	= 1<<0,  /* Rx FIFO Overflow */

	GMR_FS_ANY_ERR	= GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
			  GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
		  	  GMR_FS_MII_ERR | GMR_FS_BAD_FC |
			  GMR_FS_UN_SIZE | GMR_FS_JABBER,
};

GMR_FS_LONG_ERR被置位。

不过这之后引起了一个更严重的问题,skb校验和错误:

: hw csum failure
[16822.737321] CPU: 1 PID: 0 Comm: swapper/1 Tainted: P          IO  3.16.7-7-desktop #1
[16822.737324] Hardware name: System manufacturer System Product Name/P5B-Deluxe, BIOS 1238    09/30/2008
[16822.737327]  0000000000000000 ffffffff8161bd03 ffff8800b9a39400 ffffffff81523cb9
[16822.737334]  d9b2c8ba00000000 ffff8801577c9180 ffff88005214d762 ffff8800b9a39400
[16822.737337]  ffffffff8157ddd0 0000000000000400 0000000100000000 ffff8800b9a39400
[16822.737341] Call Trace:
[16822.737358]  [] dump_trace+0x8e/0x350
[16822.737363]  [] show_stack_log_lvl+0xa6/0x190
[16822.737368]  [] show_stack+0x21/0x50
[16822.737374]  [] dump_stack+0x49/0x6a
[16822.737380]  [] __skb_checksum_complete+0x99/0xa0
[16822.737387]  [] tcp_rcv_established+0x240/0x6c0
[16822.737393]  [] tcp_v4_do_rcv+0xdf/0x310
[16822.737398]  [] tcp_v4_rcv+0x686/0x790
[16822.737405]  [] ip_local_deliver_finish+0xa6/0x220
[16822.737411]  [] __netif_receive_skb_core+0x573/0x790
[16822.737416]  [] netif_receive_skb_internal+0x1f/0xa0
[16822.737421]  [] napi_gro_receive+0xb8/0x100
[16822.737436]  [] sky2_poll+0x752/0xcf0 [sky2]
[16822.737450]  [] net_rx_action+0x149/0x270
[16822.737461]  [] __do_softirq+0xf1/0x2d0
[16822.737464]  [] irq_exit+0x95/0xa0
[16822.737469]  [] do_IRQ+0x52/0xe0
[16822.737473]  [] common_interrupt+0x6d/0x6d
[16822.737479]  [] native_safe_halt+0x2/0x10
[16822.737483]  [] default_idle+0x19/0xf0
[16822.737487]  [] cpu_idle_loop+0x33c/0x440
[16822.737491]  [] cpu_startup_entry+0x56/0x60
[16822.737495]  [] start_secondary+0x21c/0x2e0
[16824.392887] : hw csum failure
[16824.392900] CPU: 1 PID: 0 Comm: swapper/1 Tainted: P          IO  3.16.7-7-desktop #1
[16824.392903] Hardware name: System manufacturer System Product Name/P5B-Deluxe, BIOS 1238    09/30/2008
[16824.392906]  0000000000000000 ffffffff8161bd03 ffff880080e55600 ffffffff81523cb9
[16824.392911]  56a0c4fea6089f18 ffff880044ab4740 ffff880052370062 ffff880080e55600
[16824.392917]  ffffffff8157ddd0 0000011800000000 ffff880080e55600 ffff880080e55600
[16824.392921] Call Trace:
[16824.392938]  [] dump_trace+0x8e/0x350
[16824.392948]  [] show_stack_log_lvl+0xa6/0x190
[16824.392952]  [] show_stack+0x21/0x50
[16824.392956]  [] dump_stack+0x49/0x6a
[16824.392962]  [] __skb_checksum_complete+0x99/0xa0
[16824.392967]  [] tcp_rcv_established+0x240/0x6c0
[16824.392972]  [] tcp_v4_do_rcv+0xdf/0x310
[16824.392976]  [] tcp_v4_rcv+0x686/0x790
[16824.392981]  [] ip_local_deliver_finish+0xa6/0x220
[16824.392986]  [] __netif_receive_skb_core+0x573/0x790
[16824.392990]  [] netif_receive_skb_internal+0x1f/0xa0
[16824.392994]  [] napi_gro_receive+0xb8/0x100
[16824.393007]  [] sky2_poll+0x752/0xcf0 [sky2]
[16824.393017]  [] net_rx_action+0x149/0x270
[16824.393023]  [] __do_softirq+0xf1/0x2d0
[16824.393027]  [] irq_exit+0x95/0xa0
[16824.393032]  [] do_IRQ+0x52/0xe0
[16824.393036]  [] common_interrupt+0x6d/0x6d
[16824.393042]  [] native_safe_halt+0x2/0x10
[16824.393047]  [] default_idle+0x19/0xf0
[16824.393052]  [] cpu_idle_loop+0x33c/0x440
[16824.393056]  [] cpu_startup_entry+0x56/0x60
[16824.393060]  [] start_secondary+0x21c/0x2e0
[16835.153372] : hw csum failure
[16835.153384] CPU: 1 PID: 0 Comm: swapper/1 Tainted: P          IO  3.16.7-7-desktop #1
[16835.153387] Hardware name: System manufacturer System Product Name/P5B-Deluxe, BIOS 1238    09/30/2008
[16835.153390]  0000000000000000 ffffffff8161bd03 ffff8800ba5f1c00 ffffffff81523cb9
[16835.153395]  6f66ac38a6089f18 ffff8800720db800 ffff88004f3a0062 ffff8800ba5f1c00
[16835.153398]  ffffffff8157ddd0 0000011800000000 ffff8800ba5f1c00 ffff8800ba5f1c00
[16835.153402] Call Trace:
[16835.153417]  [] dump_trace+0x8e/0x350
[16835.153423]  [] show_stack_log_lvl+0xa6/0x190
[16835.153428]  [] show_stack+0x21/0x50
[16835.153433]  [] dump_stack+0x49/0x6a
[16835.153444]  [] __skb_checksum_complete+0x99/0xa0
[16835.153449]  [] tcp_rcv_established+0x240/0x6c0
[16835.153454]  [] tcp_v4_do_rcv+0xdf/0x310
[16835.153458]  [] tcp_v4_rcv+0x686/0x790
[16835.153463]  [] ip_local_deliver_finish+0xa6/0x220
[16835.153468]  [] __netif_receive_skb_core+0x573/0x790
[16835.153473]  [] netif_receive_skb_internal+0x1f/0xa0
[16835.153476]  [] napi_gro_receive+0xb8/0x100
[16835.153488]  [] sky2_poll+0x752/0xcf0 [sky2]
[16835.153499]  [] net_rx_action+0x149/0x270
[16835.153504]  [] __do_softirq+0xf1/0x2d0
[16835.153508]  [] irq_exit+0x95/0xa0
[16835.153513]  [] do_IRQ+0x52/0xe0
[16835.153516]  [] common_interrupt+0x6d/0x6d
[16835.153522]  [] native_safe_halt+0x2/0x10
[16835.153527]  [] default_idle+0x19/0xf0
[16835.153531]  [] cpu_idle_loop+0x33c/0x440
[16835.153535]  [] cpu_startup_entry+0x56/0x60
[16835.153539]  [] start_secondary+0x21c/0x2e0
[16850.705011] : hw csum failure
[16850.705018] CPU: 1 PID: 2181 Comm: plasma-desktop Tainted: P          IO  3.16.7-7-desktop #1
[16850.705019] Hardware name: System manufacturer System Product Name/P5B-Deluxe, BIOS 1238    09/30/2008
[16850.705021]  0000000000000000 ffffffff8161bd03 ffff8800622f8c00 ffffffff81523cb9
[16850.705024]  93b387eb622f8c00 ffff8800622f8c00 ffff88005219f8c0 ffff88005219f930
[16850.705026]  ffffffff815870d1 000000000000013a ffff8800622f8c00 ffff8800622f8c00
[16850.705028] Call Trace:
[16850.705041]  [] dump_trace+0x8e/0x350
[16850.705045]  [] show_stack_log_lvl+0xa6/0x190
[16850.705048]  [] show_stack+0x21/0x50
[16850.705051]  [] dump_stack+0x49/0x6a
[16850.705056]  [] __skb_checksum_complete+0x99/0xa0
[16850.705060]  [] tcp_v4_do_rcv+0x161/0x310
[16850.705065]  [] tcp_v4_rcv+0x686/0x790
[16850.705069]  [] ip_local_deliver_finish+0xa6/0x220
[16850.705073]  [] __netif_receive_skb_core+0x573/0x790
[16850.705077]  [] netif_receive_skb_internal+0x1f/0xa0
[16850.705080]  [] napi_gro_receive+0xb8/0x100
[16850.705092]  [] sky2_poll+0x752/0xcf0 [sky2]
[16850.705102]  [] net_rx_action+0x149/0x270
[16850.705107]  [] __do_softirq+0xf1/0x2d0
[16850.705110]  [] irq_exit+0x95/0xa0
[16850.705114]  [] do_IRQ+0x52/0xe0
[16850.705117]  [] common_interrupt+0x6d/0x6d
[16850.705125]  [] 0x7f1fe79caf2d

原因是sky2开了硬件校验和,但校验值为0,且已置位相关标志,导致到__skb_checksum_complete时触发了一次内核dump:

__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
{
	__sum16 sum;

	sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
	if (likely(!sum)) {
		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
			netdev_rx_csum_fault(skb->dev);
		skb->ip_summed = CHECKSUM_UNNECESSARY;
	}
	return sum;
}
EXPORT_SYMBOL(__skb_checksum_complete_head);

__sum16 __skb_checksum_complete(struct sk_buff *skb)
{
	return __skb_checksum_complete_head(skb, skb->len);
}


void netdev_rx_csum_fault(struct net_device *dev)
{
	if (net_ratelimit()) {
		pr_err("%s: hw csum failure\n", dev ? dev->name : "");
		dump_stack();
	}
}

看来marvell的网卡一定有个寄存器存放mtu值,供收包时检查。

sky2.c有如下代码:

static int sky2_change_mtu(struct net_device *dev, int new_mtu)
{
	struct sky2_port *sky2 = netdev_priv(dev);
	struct sky2_hw *hw = sky2->hw;
	unsigned port = sky2->port;
	int err;
	u16 ctl, mode;
	u32 imask;

	/* MTU size outside the spec */
	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
		return -EINVAL;

	/* MTU > 1500 on yukon FE and FE+ not allowed */
	if (new_mtu > ETH_DATA_LEN &&
	    (hw->chip_id == CHIP_ID_YUKON_FE ||
	     hw->chip_id == CHIP_ID_YUKON_FE_P))
		return -EINVAL;

	if (!netif_running(dev)) {
		dev->mtu = new_mtu;
		netdev_update_features(dev);
		return 0;
	}

	imask = sky2_read32(hw, B0_IMSK);
	sky2_write32(hw, B0_IMSK, 0);

	dev->trans_start = jiffies;	/* prevent tx timeout */
	napi_disable(&hw->napi);
	netif_tx_disable(dev);

	synchronize_irq(hw->pdev->irq);

	if (!(hw->flags & SKY2_HW_RAM_BUFFER))
		sky2_set_tx_stfwd(hw, port);

	ctl = gma_read16(hw, port, GM_GP_CTRL);
	gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
	sky2_rx_stop(sky2);
	sky2_rx_clean(sky2);

	dev->mtu = new_mtu;
	netdev_update_features(dev);

	mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |	GM_SMOD_VLAN_ENA;
	if (sky2->speed > SPEED_100)
		mode |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
	else
		mode |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);

	if (dev->mtu > ETH_DATA_LEN)
		mode |= GM_SMOD_JUMBO_ENA;

	gma_write16(hw, port, GM_SERIAL_MODE, mode);

	sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);

	err = sky2_alloc_rx_skbs(sky2);
	if (!err)
		sky2_rx_start(sky2);
	else
		sky2_rx_clean(sky2);
	sky2_write32(hw, B0_IMSK, imask);

	sky2_read32(hw, B0_Y2_SP_LISR);
	napi_enable(&hw->napi);

	if (err)
		dev_close(dev);
	else {
		gma_write16(hw, port, GM_GP_CTRL, ctl);

		netif_wake_queue(dev);
	}

	return err;
}
static void sky2_rx_start(struct sky2_port *sky2)
{
..........
	thresh = sky2_get_rx_threshold(sky2);
	if (thresh > 0x1ff)
		sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
	else {
		sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
		sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
	}
.........
}

mtu写进了网卡的寄存器,收包的时候也会检测,发现超过mtu的会置status位,也就是开头的那个检查点。相反intel的e1000和igb根本不关心mtu,只是和jumbo frame有关系的代码会与mtu有点联系。

某些ISP无耻的http劫持

偶尔逛下taobao发现经常打开的是空白页,瞬间联想到了ISP的劫持,看了下代码发现流氓比之前更加有文化了:自己不再直接生成iframe页面,改用js,让客户浏览器生成,为了是减小现网劫持设备的负载,躲避反劫持侦测。而且使用了内嵌js和代码混淆。

对于这种支持https的站点可以在chrome的hsts中增加域名来跳过https跳转,直接访问。
但全站https在镇上短期是不现实的,因为https在CDN和缓存内容上实施起来有困难,镇上为了短期效益和某些不想扯上关系的利益攸有关方还需要妥协一段时间。不过总的来说这是趋势。

某大神眼中的编程语言

CCL6PYwUgAAZml1

一张图说明软件开发的过程

software_industray