Living a Simple Life is a Happy Life

有饭吃,自由自在,就非常开心

海淘和跨境电商ABC

| Comments

补习了一下海淘和跨境电商的一些基本知识。

首先海淘和跨境电商不是同一个概念,两者的区别在于,海淘除了跨境模式正规申报进境外,还有“海外代购”和“境外购买后通过转运入境”两种情况。

按照时间顺序来一遍行业发展史吧

2013年10月1日之前

这是蛮荒时代,海外代购商品与在境外电商平台购买后通过转运公司运至国内的商品,大多是通过包裹邮递渠道进境,与通过跨境申报进境的商品一样,都以参照物品征收“行邮税”,这意味着通过跨境电商模式进境的商品,被当作物品来征管。

相比较“货物”的诸多税费,“物品”享受行邮税的低税率优惠政策。就像淘宝刚开始因为没有税费而迅猛发展一样,各路海外代购买手或平台纷纷发展迅猛。

此时,海淘就是行邮模式。没有跨境电商这个概念。

2013年10月1日之后

国务院办公厅转发商务部《关于适时支持跨境电子商务零售出口的有关政策的意见》后,电子商务通关服务试点率先在上海、重庆、杭州和宁波等五城市开展,此时除了蛮荒时代的海淘之外,正规军又有了两种模式:跨境零售进口直邮模式、跨境零售进口保税备货模式。

  • 跨境零售进口直邮模式:

国内消费者在电商网站购买境外商品,由电商海外仓库直接发送包裹,邮寄给国内消费者。

  • 跨境零售进口保税备货模式

电商企业从境外直接采购货物,运送至国内海关保税区内备货,国内消费者从其网站购买商品后,电商直接从海关特殊监管区域发货,送达消费者。

这两大模式不同于海外代购,跨境商品需要电商企业向海关系统发送“物流信息”,“订单信息”和“支付信息”,同时进行清单申报。此时的货物都按照物品实行的行邮税来征税,而行邮税是将关税、增值税、消费税合并在一起征收,远低于一般贸易商品需征收的税额。

此时的市场如下:

  • 海淘模式

一批朋友圈个人买手,或者个人消费者美亚或亚马逊,这是散户。他们一般走转运,渠道有阳光和非阳光,征税看天命,价格优势明显。 然后洋码头和天猫国际做的是散户平台C2C,有点像海淘版的淘宝,物流和服务上有所保障。

  • 跨境零售进口直邮模式

玩这个的一般是天猫或者京东B2C的入驻商家。这个成本太高,所以一般主打个性化的牌。

  • 跨境零售进口保税备货模式

这个模式就是跨境电商的主流了,既有B2C,又有B2B,可以说这几年享尽了政策红利,所以基本上有钱的主一拥而上。现在有点名号的估计都在保税区占着个仓库。

2016年4月8日之后

这么挣钱实在太爽了,而且有偷税之嫌,肯定有人眼红啦。所以当当当当,4月8日实施了一个跨境电商税收政策,这个政策比较细,内容比较多,可以直接去看知乎:

https://www.zhihu.com/question/41749303

总之就是,行邮税提升,保税区里面的货要征收关税、增值税和消费税。

这么看,其实对大佬来说没多大影响,他们之前本来就正规交税,无非是为了行业规范出点买路钱,肉痛一点,但还是比一般贸易商品征税爽啊。

散户的影响不好说,要看你的主力购买什么东西,可能有升有降,而且还有走灰色渠道进来的,可能还是个利好,因为正规一点的对手成本增加了。

但是…..这个政策绝对是一拨人拍了脑袋,最后没有一个人全盘想明白,就出来的,因为….4月7日,财政部、发展改革委、工业和信息化部、农业部、商务部、海关总署、国家税务总局、质检总局、食品药品监管总局、濒管办、密码局等11个部门共同公布了《跨境电子商务零售进口商品清单》。

看到这么多人共同出的一个东西,相信对中国政策有点了解的人都会打哆嗦。

这个清单里很多东西都要证明和各种检疫报告之类的东西–>这些证明的取得不是一年半载就能有的—>然后你懂的….

相信很多保税区现在已经是人迹寥落了,相信很多大佬都在开会拍脑袋了…….

这份清单对于 跨境零售进口保税备货模式的人来说,真乃核打击。

对于散户和个人买手来说,赶紧去发掘灰色渠道,有笔快钱能挣。

对于洋码头这种走C2C的模式来说,影响肯定有,但是不好说有多大。

对于跨境电商和海淘业务的一点YY

下面的内容纯属一个码农的YY

  • 跨境电商实际上是对传统外贸模式的一种颠覆。首先,既得利益团体不会内部革命,所以跨境电商是农村包围城市之计

  • 中国的电商业务其实已经笑傲全球了,可能不论是技术上、业务模式创新上,绝对全球领先

  • 和早期国内做电子商务不同,那个时候没有人看好,只有两三家,现在的跨境电商是军阀割据,什么招都有,什么B2B,B2C,C2C, O2O,平台入驻的,微博营销的,微信朋友圈的,走正路的,走歪路的,反正是沸沸扬扬

  • 国家一方面不希望传统的一般贸易被冲击,又想释放国内的消费能力多征点税,种种纠结之下,估计会政令频发,调整频繁

  • 总之,这绝对是个风口,至于是上风口还是下风口,得看天时地利人和,缺一不可

  • 挑战与机遇并存啦,可能玩的就是心跳,也可能过把瘾就死

从一个码农的角度看业务支撑

  • 这种环境可说是乱花迷人眼,由于政策变化,一年之内战略改个三五次都有可能,估计各家就是要拼运营,拼后台支撑了

  • 哪种组合能挣钱,估计一个脑子想不明白了。我觉得得有一张大表,每种模式,每个 case都画出来,然后隔一个周就填一遍所有流程的成本,看看行业变化是什么

  • 这个行当这是有点像改革开发初期搞外贸啊……….

Open vSwitch Bridge and NetworkNameSpace Command Cheat

| Comments

  • 启动

      service openvswitch start
    
  • 创建网桥

      ovs-vsctl add-br br0
      ifconfig br0 up
    
  • 显示所有网桥

      ovs-vsctl show
    
  • 删除网桥

      ovs-vsctl del-br br0
    
  • 增加端口

      ovs-vsctl add-port br0 eth0
    
  • 设置网卡为none

      dhclient br0
    
  • 用 Namespace 模拟两台虚拟机网络

      p netns add network1
      ip netns add network2
    
  • 创建两个虚拟网卡并加入网桥

      ovs-vsctl add-port br0 vport1 -- set interface vport1 type=internal
      ovs-vsctl add-port br0 vport2 -- set interface vport2 type=internal
      tunctl -p -t vport1
      tunctl -p -t vport2
    
  • 两个虚拟网卡接入namespace

      ip link set vport1 netns network1
      ip link set vport2 netns network2
    
  • 设置虚拟网卡的IP

      ip netns exec network1 ifconfig vport1 192.168.0.1/24 up
      ip netns exec network2 ifconfig vport2 192.168.0.2/24 up
    
  • 两个namsespace PING

      ip netns exec network1 ping 192.168.0.2
      ip netns exec network2 tcpdump -i vport2
    
  • 两个namsespace NC传输

      ip netns exec network2 nc -l 1234
      ip netns exec network2 tcpdump -i vport2
      ip netns exec network1 nc 192.168.0.2 1234
    
  • 显示vlan信息

      ovs-appctl fdb/show br0
    
  • 显示openflow信息

      ovs-ofctl show br0
    
  • 显示流表信息

      ovs-ofctl dump-flows br0
    
  • 显示网桥详细信息

      ovs-vsctl list Bridge
    
  • 显示端口详细信息

      ovs-vsctl list Port
    
  • 显示接口详细信息

      ovs-vsctl list Interface
    

Webtorrent Redefine CDN?

| Comments

最近发现了一个开源的JS东东,webtorrent:

https://github.com/feross/webtorrent

用webRTC实现了一个浏览器端的bt客户端。

这个点子我还在几年前试过呢?当时想用socketio来做,但各种限制,当时webRTC还是个小众,没有被浏览器主流实现。

试了一下,效果还差强人意。

脑洞开一下,话说这会不会是快播们的春天来了。

严肃一点再想想,是不是CDN提供商们可以利用它分担压力,提升速度,走上人生巅峰….

留待后续观察。

有关于云计算及SDN

| Comments

云计算和SDN这两个名词总是被许多人挂在嘴边,他们给人的印象就是在Qcon大会上念PPT的一拨人。

作为一个实用党,下面我企图用一问一答的形式来瞎扯一番:

Q: 我是个中小企业,用openstack好还是vCenter虚拟化好?

A: 如果你能招到一个合适的人(注意,这个概率我觉得是万分之一),你可以上openstack。

如果你有足够的M,上vCenter。

如果你什么都没有,上阿里云 (我是认真的,不要黑我)。

总之,随着网络带宽提升,我觉得中小企业自建运维越来越不划算。云化是趋势。

Q: 容器技术会颠覆现有的虚拟化技术吗?

A: 不会,容器技术只是补充,全虚拟化有自己不可替代优势。

Q: SDN会替代现在的网络设备吗?

A: 可能会替代大部分网络交换设备。但是就现在的情况来看,各种SDN解决方案的性能还没有和硬件处在同一档次上。

所以将来在大型数据中心,肯定是软硬结合和持续很长一段时间。

在很多中小云平台,大部分硬件设备已经在迁移过程中了。

Q: SDN真的比传统设备灵活吗?简单吗?方便吗?

A: 首先要看方案,和传统网络一样,不同的场景实施方案也不一样。一千个现场会有一千个云实施方案。

SDN有灵活性的优势。

SDN某种意义上说,比传统网络还要复杂。

首先,真实世界的网络就是复杂的。任何隐藏复杂性的尝试都会增加复杂性。所以SDN不能拯救世界,传统硬件设备面临的复杂问题,它也一样要面对。

SDN的优势就是灵活,并非简单。

Q: 未来从事中小企业云的部署咨询工作,有戏吗?

A: 我觉得单纯做部署顾问之类的没戏。做openstack的番茄花园有戏。

如果将来GPU虚拟化成熟的话,做打金工作室的openstack 包装发行版相当有戏。

Q: SDN领域有何机会?

A: 也许SDN领域将来不会再孕育思科华为那样的大玩家,但是一定会有许多独角兽出来。

目前看到的看准一个痛点,比如苏州盛科那样,软硬结合,做芯片,交换机白牌供应商,很有机会。

或者瞅准市场空白,比如说做性能比较低的软tap,我觉得很有戏。

Is Craig Wright Real Satoshi Nakamoto?

| Comments

Craig Wright 又在声明他是”中本聪”了.

“中本聪”给出的签名是:

MEUCIQDBKn1Uly8m0UyzETObUSL4wYdBfd4ejvtoQfVcNCIK4AIgZmMsXNQWHvo6KDd2Tu6euEl13VTC3ihl6XUlhcU+fM4=

我们先对信息串进行base64解码,再转换成hex是:

3045022100c12a7d54972f26d14cb311339b5122f8c187417dde1e8efb6841f55c34220ae0022066632c5cd4161efa3a2837764eee9eb84975dd54c2de2865e9752585c53e7cce

很遗憾,我们可以在交易ID:

828ef3b079f9c23829c56fe86e85b4a69d9e06e5b54ea597eef5fb3ffef509fe

中找出这个签名。可通过:

https://blockchain.info/tx/828ef3b079f9c23829c56fe86e85b4a69d9e06e5b54ea597eef5fb3ffef509fe?format=hex

找到十六进制串的交易内容

然后搜索一下hex样子的签名,遗憾地发现,能在这个交易中找到这个签名。

但是令人疑惑的是GAVIN ANDRESEN为这位”中本聪”背书:

http://gavinandresen.ninja/satoshi

Gavin不是一个无的放矢的人,他肯定是见到了更多的证据.

但是Craig Wright 又不对其他给定的文本签名来证明自己是中本聪,反而老是用这种神神遭遭的签名来忽悠大家……

卫平布莱恩特老师说,这球有意思啊…….

最后, 如果Craig Wright这个人是为了某种目的假冒的话,只能说他真是煞费苦心啊. 我不认为一个签名造假如此low的家伙能有这种能力.

但是他的一些行为如果算恶作剧的话,又未免太高段了,参考这里:

https://www.zhihu.com/question/22199390/answer/76083139

不负责任的YY一下, Craig Wright肯定和真正的中本聪有某种关系,他在bitcoin诞生之初就了解参与过.

他不是bitcoin的发明者,因为种种迹象表明,他的技术能力实在太low了.

真正的中本聪可能是他的那个朋友:David Kleiman, 但他已经死了.

呵呵, 绝佳的侦探小说体裁啊.

Git Cheat 2

| Comments

整理一下经常忘记的Git命令 (版本v2)

http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html?utm_source=tool.lu

新建代码库

# 在当前目录新建一个Git代码库
git init

# 新建一个目录,将其初始化为Git代码库
git init [project-name]

# 下载一个项目和它的整个代码历史
git clone [url]

配置

Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。

# 显示当前的Git配置
git config --list

# 编辑Git配置文件
git config -e [--global]

# 设置提交代码时的用户信息
git config [--global] user.name "[name]"
git config [--global] user.email "[email address]"

增加/删除文件

# 添加指定文件到暂存区
git add [file1] [file2] ...

# 添加指定目录到暂存区,包括子目录
git add [dir]

# 添加当前目录的所有文件到暂存区
git add .

# 删除工作区文件,并且将这次删除放入暂存区
git rm [file1] [file2] ...

# 停止追踪指定文件,但该文件会保留在工作区
git rm --cached [file]

# 改名文件,并且将这个改名放入暂存区
git mv [file-original] [file-renamed]

代码提交

# 提交暂存区到仓库区
git commit -m [message]

# 提交暂存区的指定文件到仓库区
git commit [file1] [file2] ... -m [message]

# 提交工作区自上次commit之后的变化,直接到仓库区
git commit -a

# 提交时显示所有diff信息
git commit -v

# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
git commit --amend -m [message]

# 重做上一次commit,并包括指定文件的新变化
git commit --amend [file1] [file2] ...

分支

# 列出所有本地分支
git branch

# 克隆并在本地建立所有分支

for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
    git branch --track ${branch##*/} $branch
done

# 列出所有远程分支
git branch -r

# 列出所有本地分支和远程分支
git branch -a

# 新建一个分支,但依然停留在当前分支
git branch [branch-name]

# 新建一个分支,并切换到该分支
git checkout -b [branch]

# 新建一个分支,指向指定commit
git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
git branch --track [branch] [remote-branch]

# 切换到指定分支,并更新工作区
git checkout [branch-name]

# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支
git merge [branch]

# 选择一个commit,合并进当前分支
git cherry-pick [commit]

# 删除分支
git branch -d [branch-name]

# 删除远程分支
git push origin --delete [branch-name]

# 删除不存在对应远程分支的本地分支
# 假设这样一种情况:
#    1. 我创建了本地分支b1并push到远程分支 origin/b1;
#    2. 其他人在本地使用fetch或pull创建了本地的b1分支;
#    3. 我删除了 origin/b1 远程分支;
#    4. 其他人再次执行fetch或者pull并不会删除这个他们本地的 b1 分支,运行 git branch -a 也不能看出这个branch被删除了,如何处理?

# 在fetch之后删除掉没有与远程分支对应的本地分支
git fetch -p                                                        //

# 重命名远程分支
# 在git中重命名远程分支,其实就是先删除远程分支,然后重命名本地分支,再重新提交一个远程分支
git push --delete origin devel
git branch -m devel develop
git push origin develop

# 合并branchB到branchA
# 前提是你需要的是fast-forward
# 合并本地的branchB到本地的branchA
git fetch . branchB:branchA

# 合并远端的branchB到本地的branchA
git fetch origin branchB:branchA


# 合并branch上的指定文件
# branches/A 上修改了一个文件A.h,新增了一个文件B.h,删除了一个文件C.h。
# 首先切换到master分支
git checkout master
# 不切换branch,把RemLanbranches/A上的A.h更新到当前分支
git checkout -p branches/A A.h
# 去掉-p参数,新增该B.h文件
git checkout branches/A B.h
# 删除文件目前还没找到其他办法,但效果是一样的
rm C.h

标签

# 列出所有tag
git tag

# 新建一个tag在当前commit
git tag [tag]

# 新建一个tag在指定commit
git tag [tag] [commit]

# 删除本地tag
git tag -d [tag]

# 删除远程tag
git push origin :refs/tags/[tagName]

# 查看tag信息
git show [tag]

# 提交指定tag
git push [remote] [tag]

# 提交所有tag
git push [remote] --tags

# 新建一个分支,指向某个tag
git checkout -b [branch] [tag]

查看信息

# 显示有变更的文件
git status

# 显示当前分支的版本历史
git log

# 显示commit历史,以及每次commit发生变更的文件
git log --stat

# 显示某个commit之后的所有变动,每个commit占据一行
git log [tag] HEAD --pretty=format:%s

# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
git log [tag] HEAD --grep feature

# 显示某个文件的版本历史,包括文件改名
git log --follow [file]
git whatchanged [file]

# 显示指定文件相关的每一次diff
git log -p [file]

# 显示指定文件是什么人在什么时间修改过
git blame [file]

# 显示暂存区和工作区的差异
git diff

# 显示暂存区和上一个commit的差异
git diff --cached [file]

# 显示工作区与当前分支最新commit之间的差异
git diff HEAD

# 显示两次提交之间的差异
git diff [first-branch]...[second-branch]

# 显示某次提交的元数据和内容变化
git show [commit]

# 显示某次提交发生变化的文件
git show --name-only [commit]

# 显示某次提交时,某个文件的内容
git show [commit]:[filename]

# 显示当前分支的最近几次提交
git reflog

远程同步

# 下载远程仓库的所有变动
$ git fetch [remote]

# 显示所有远程仓库
$ git remote -v

# 显示某个远程仓库的信息
$ git remote show [remote]

# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]

# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]

# 上传本地指定分支到远程仓库
$ git push [remote] [branch]

# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force

# 推送所有分支到远程仓库
$ git push [remote] --all

撤销

# 恢复暂存区的指定文件到工作区
git checkout [file]

# 恢复某个commit的指定文件到暂存区和工作区
git checkout [commit] [file]

# 恢复暂存区的所有文件到工作区
git checkout .

# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
git reset [file]

# 重置暂存区与工作区,与上一次commit保持一致
git reset --hard

# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
git reset [commit]

# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
git reset --hard [commit]

# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
git reset --keep [commit]

# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
git revert [commit]

remote 同步

# 查看当前远程版本库
git remote -v

#添加原始版本库
git remote add cocos2d-x git://github.com/cocos2d/cocos2d-x.git

#获取原始版本库的更新
git fetch cocos2d-x

# 合并原始版本库的代码到当前版本库中,合并前确保当前分支是master
git merge cocos2d-x/master

分支的衍合

http://git-scm.com/docs/git-rebase

diff

# 只显示两个分支间的差异,如果你想找出‘master’,‘test’的共有 父分支和'test'分支之间的差异,你用3个‘.'来取代前面的两个'.' 。
git diff master..test

# 显示你当前的索引和上次提交间的差异;这些内容在不带"-a"参数运行 "git commit"命令时就会被提交。
git diff --cached

# 显示你工作目录与上次提交时之间的所有差别,这条命令所显示的 内容都会在执行"git commit -a"命令时被提交。
git diff HEAD

# 如果你要查看当前的工作目录与另外一个分支的差别,你可以用下面的命令执行:
#这会显示你当前工作目录与另外一个叫'test'分支的差别。你也以加上路径限定符,来只 比较某一个文件或目录。
git diff test

# 显示你当前工作目录下的lib目录与上次提交之间的差别(或者更准确的 说是在当前分支)。
git diff HEAD -- ./lib

# 如果不是查看每个文件的详细差别,而是统计一下有哪些文件被改动,有多少行被改 动,就可以使用‘--stat' 参数。
git diff --stat

# 显示两次更改之间所有的文件名
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRTD HEAD HEAD^

# diff两个分支
git diff master branch/1.1 --

其他

# 生成一个可供发布的压缩包
git archive

# 临时保存/恢复现在的状态
git stash
git stash pop

# svn log -v 类似效果
git log --name-status

Migrate Centos7 From Centos6

| Comments

工作环境切换到Centos7 半年有余,epel仓库里的软件版本比el6更新了不少,非常方便。

另外systemd的引入让很多程序,尤其是开机启动上,速度提升了不少。

总体来说,很多细节让你感觉很舒服,值得大家尽快切换到这个版本上了。

下面记一下从Centos6迁移到Centos7上 常见的Question:

Q: 为什么引入systemd 代替 SysV init,我就是习惯原来的 /etc/init.d/xxxx 的方法?

A: 在我看来,有两点:

  1. 快。 真的是快,嗖嗖的快

  2. 日志。 终于能取代syslog了,我对syslog素无好感,配置复杂,level巨多,还不好排障。

参考资料:

http://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/

https://wiki.archlinux.org/index.php/Systemd

Q: 为什么网卡名字这么奇怪,我要原来的简单明了的办法!!!

A: 呃,好吧,我觉得虽然有一堆理由,但是网卡名字这个改变可能真的是没有产品经理的弊端。你想回到从前,很简单:

  • 在 grub 加入 net.ifnames=0 and biosdevname=0 作为内核参数

  • 在 /etc/sysconfig/network-scripts/ 内把你的网络卡配置文件换名为 ifcfg-ethX

  • 假若你拥有多个界面并希望控制每个设备的名称,不想由内核作主,你似乎有必要通过 /etc/udev/rules.d/60-net.rules 盖过 /usr/lib/udev/rules.d/60-net.rules。

Q: grub.cfg 文件生成怎么这个奇怪,还要先配置 /etc/default/grub,再用命令生成一遍?我要直接改!!

A: 醒醒吧,我对这个改动双手赞成,至少她解决了centos6上一直被人诟病的efi问题。

Q: 嗯,我想问,ifconfig和 netstat哪里去了?

A: 额,套用官方原话回答吧:

ifconfig 及 netstat 工具程序在 CentOS 5 及 6 的应用手册内被置标为降级已接近十年,而 Redhat 决定在 CentOS 7 不会缺省安装 net-utils 组件。取而代之的工具是 ss 和 ip 。假如你真的、真的很需要 ifconfig 和 netstat,你可执行 yum install net-utils。

更多请参考:

https://wiki.centos.org/zh/FAQ/CentOS7#head-d04a9f331b47791774aefd7c11371934e7350ab3

Send Large Packet by Dpdk Pktgen

| Comments

场景

测试qinq 发包,但是tcpreplay是没法带vlan tag的。所以需要用pktgen发送qinq包。

问题

qinq双层vlan tag,有些包大小超过了1518字节,pktgen不支持。

解决方案

修改 dpdk-2.1.0/x86_64-native-linuxapp-gcc/include/rte_ether.h:

#define ETHER_MAX_LEN 1522

重新编译DPDK,Pktgen,重新加载DPDK驱动

资料

  • DPDK2.1.0:

http://dpdk.org/browse/dpdk/snapshot/dpdk-2.1.0.tar.gz

  • Pktgen2.9.5:

http://dpdk.org/browse/apps/pktgen-dpdk/snapshot/pktgen-dpdk-pktgen-2.9.5.tar.gz

Capture QinQ Large Packets

| Comments

最近遇到一个QinQ的问题,总结一下。

对QinQ协议的交换机做Span,tcpdump抓包后发现,有一些包大小为1522字节,这些包都被网卡丢掉了。仔细排查后发现,网卡对于>1518的包,统一丢掉处理了。

简单的解决办法,就是将网卡的mtu增大,设置为1508或者直接1600,就OK了。

事情虽小,但还是有不少知识点的,归纳一下:

QinQ

简介

IEEE 802.1ad或称为QinQ、vlan stacking。是一种以802.1Q为基础衍生出来的通讯协定。

QinQ报文有固定的格式,就是在802.1Q的标签之上再打一层802.1Q标签,QinQ报文比正常的802.1Q报文多4个字节。这4个字节用作外层标签,即运营商网络的公网VLAN Tag。原802.1Q的Tag用作内层标签,即私网VLAN Tag。

可以参考这张图:

https://zh.wikipedia.org/wiki/IEEE802.1ad#/media/File:TCPIP802.1ad_DoubleTag.svg

QinQ的出现,扩充了原始的vlan个数,由4094 -> 4094*4094。

QinQ的作用,在大规模组网时,或者建立Paas云时,可以允许不同的租户设置相同的vlan id。

并不是所有的交换机都支持QinQ的,QinQ只是一个草案,需要交换机厂商的支持。

下面从wiki上摘抄一个典型例子:

Acme及XYZ分别在Seattle及Tacoma有一间分公司,并借由SP的L2 VPN网络连线,而他们的子公司都使用相同的LAN。 换句话说,我们可以假设,Acme使用VLAN 100-200并透过SP连结两间子公司的网络;XYZ也使用VLAN 100-200并使用SP的网络连结子公司。

而对SP而言,则必须想办法区隔Acme及XYZ的资料,使其有办法通过SP的网络并分别送至各自的子公司。

解决办法就是,使用VLAN STACKING来区隔Acme及XYZ的资料。

当Acme送出资料时,SP使用QinQ并给予该资料一个独特的SPVID 1001,使其能通过SP的网络并流向另外一间子公司,当到达子公司则移除该SPVID,该资料便能依照原始的VLAN ID进行传送。而XYZ送出资料时,SP则使用SPVID 1002来区隔。

包长

QinQ比正常的报文多了4个字节,所以QinQ报文,在链路层,最大包长到了1522个字节。

标准的Ethernet V2中,IP报文最大不超过1500字节,加上DA+SA+TYPE+DATA+PAD, 链路层的以太网帧最小为60字节,最大为1514字节,如果是802.1q,带有vlan tag,会有1518字节。

QinQ的最大包长明显超出了,在大多数网卡驱动中,默认配置下,这种包是会被丢弃掉的。好在交换机会自动处理这种情况,确保包最终到我们的网卡时,是符合Ethernet V2的。

但是直接对交换机端口做Span,网卡便傻掉了。

阅读linux tg3驱动源码发现,丢弃此类包的判断是很简单的:

10188         /* MTU + ethernet header + FCS + optional VLAN tag */
10189         tw32(MAC_RX_MTU_SIZE,
10190              tp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
10191

http://lxr.free-electrons.com/source/drivers/net/ethernet/broadcom/tg3.c#L88

所以只要把网卡的mtu改改大就可以了:

ifconfig ethx mtu 1600 up

再说说以太网帧的大小

根据rfc894的说明,以太网封装IP数据包的最大长度是1500字节,也就是说以太网最大帧长应该是以太网首部加上1500,再加上7字节的前导同步码和1字节的帧开始定界符,具体就是:7字节前导同步码 + 1字节帧开始定界符 + 6字节的目的MAC + 6字节的源MAC + 2字节的帧类型 + 1500 + 4字节的FCS。

按照上述,最大帧应该是1526字节,但是实际上我们抓包得到的最大帧是1514字节,为什么不是1526字节呢?

原因是当数据帧到达网卡时,在物理层上网卡要先去掉前导同步码和帧开始定界符,然后对帧进行CRC检验,如果帧校验和出错,就丢弃此帧。如果校验和正确,就判断帧的目的硬件地址是否符合自己的接收条件(目的地址是自己的物理硬件地址、广播地址、可接收的多播硬件地址等),如果符合,就将帧交给“设备驱动程序”做进一步处理。这时我们抓包的软件才能抓到数据,因此,抓包软件抓到的是去掉前导同步码、帧开始分界符、FCS之外的数据,其最大值是6 + 6 + 2 + 1500 = 1514。

以太网规定,以太网帧数据域部分最小为46字节,也就是以太网帧最小是 6 + 6 + 2 + 46 + 4 = 64。除去4个字节的FCS,因此,抓包时就是60字节。当数据字段的长度小于46字节时,MAC子层就会在数据字段的后面填充以满足数据帧长不小于64 字节。由于填充数据是由MAC子层负责,也就是设备驱动程序。不同的抓包程序和设备驱动程序所处的优先层次可能不同,抓包程序的优先级可能比设备驱动程序更高,也就是说,我们的抓包程序可能在设备驱动程序还没有填充不到64字节帧的时候,已经捕获了数据。因此不同的抓包工具抓到的数据帧的大小可能不同。(比如,wireshark抓到的可能没有填充数据段,而sniffer抓到的就有填充数据段)

那么以太网帧格式一共有多少种呢

历史上以太网帧格式有五种:

1 Ethernet V1

这是最原始的一种格式,是由Xerox PARC提出的3Mbps CSMA/CD以太网标准的封装格式,后来在1980年由DEC,Intel和Xerox标准化形成Ethernet V1标准

2 Ethernet II即DIX 2.0

Xerox与DEC、Intel在1982年制定的以太网标准帧格式。Cisco名称为:ARPA。

这是最常见的一种以太网帧格式,也是今天以太网的事实标准,由DEC,Intel和Xerox在1982年公布其标准,主要更改了Ethernet V1的电气特性和物理接口,在帧格式上并无变化;

Ethernet V2出现后迅速取代Ethernet V1成为以太网事实标准; Ethernet V2帧头结构为6bytes的源地址+6bytes的目标地址+2Bytes的协议类型字段+数据。 常见协议类型如下:

  • 0800 IP
  • 0806 ARP
  • 0835 RARP
  • 8137 Novell IPX
  • 809b Apple Talk

如果协议类型字段取值为0000-05dc(十进制的0-1500),则该帧就不是Ethernet V2(ARPA)类型了,而是下面讲到的三种802.3帧类型之一;Ethernet可以支持TCP/IP,Novell IPX/SPX,Apple Talk Phase I等协议;RFC 894定义了IP报文在Ethernet V2上的封装格式;

下面给一张图,就对这种帧格式一目了然了:

+-----+-----+------+-----+-------+------+------+-------+
|PR   |SD   |DA    |SA   |TYPE   |DATA  |PAD   |FCS    |
+-----+-----+------+-----+-------+------+------+-------+
|56b  |8b   |48b   |48b  |16b    |<=1500|不够   | 32b   |
|     |     |      |     |       |      |填充   |       |
+-----+-----+------+-----+-------+------+------+-------+

在每种格式的以太网帧的开始处都有64比特(8字节)的前导字符,如图所示。其中,前7个字节称为前同步码(Preamble),内容是16进制数0xAA,最后1字节为帧起始标志符0xAB,它标识着以太网帧的开始。前导字符的作用是使接收节点进行同步并做好接收数据帧的准备。

  • PR:同步位,用于收发双方的时钟同步,同时也指明了传输的速率(10M和100M的时钟频率不一样,所以100M网卡可以兼容10M网卡),是56位的二进制数101010101010…..

  • SD: 分隔位,表示下面跟着的是真正的数据,而不是同步时钟,为8位的10101011,跟同步位不同的是最后2位是11而不是10.

  • DA:目的地址,以太网的地址为48位(6个字节)二进制地址,表明该帧传输给哪个网卡.如果为FFFFFFFFFFFF,则是广播地址,广播地址的数据可以被任何网卡接收到.

  • SA:源地址,48位,表明该帧的数据是哪个网卡发的,即发送端的网卡地址,同样是6个字节.

  • TYPE:类型字段,表明该帧的数据是什么类型的数据,不同的协议的类型字段不同。如:0800H 表示数据为IP包,0806H 表示数据为ARP包,814CH是SNMP包,8137H为IPX/SPX包,(小于0600H的值是用于IEEE802的,表示数据包的长度。)

  • DATA:数据段 ,该段数据不能超过1500字节。因为以太网规定整个传输包的最大长度不能超过1514字节。(14字节为DA,SA,TYPE)

  • PAD:填充位。由于以太网帧传输的数据包最小不能小于60字节, 除去(DA,SA,TYPE 14字节),还必须传输46字节的数据,当数据段的数据不足46字节时,后面补000000…..(当然也可以补其它值)

  • FCS:32位数据校验位.为32位的CRC校验,该校验由网卡自动计算,自动生成,自动校验,自动在数据段后面填入.对于数据的校验算法,我们无需了解.

事实上,PR,SD,PAD,FCS这几个数据段我们不用理它 ,它是由网卡自动产生的,我们要理的是DA,SA,TYPE,DATA四个段的内容.

所有数据位的传输由低位开始(但传输的位流是用曼彻斯特编码的)

以太网的冲突退避算法就不介绍了,它是由硬件自动执行的.

DA+SA+TYPE+DATA+PAD最小为60字节,最大为1514字节.

以太网卡可以接收三种地址的数据,一个是广播地位,一个是多播地址(我们用不上),一个是它自已的地址.但网卡也可以设置为接收任何数据包(用于网络分析和监控).

任何两个网卡的物理地址都是不一样的,是世界上唯一的,网卡地址由专门机构分配.不同厂家使用不同地址段,同一厂家的任何两个网卡的地址也是唯一的.根据网卡的地址段(网卡地址的前三个字节),可以知道网卡的生产厂家.有些网卡的地址也可以由用户去设定,但一般不需要.

3 Ethernet 802.3 raw帧格式

在Ethernet 802.3 raw类型以太网帧中,原来Ethernet II类型以太网帧中的类型字段被”总长度”字段所取代,它指明其后数据域的长度,其取值范围为:46-1500。

接下来的2个字节是固定不变的16进制数0xFFFF,它标识此帧为Novell以太类型数据帧。

这种格式的来源历史非常晦涩,这是1983年Novell发布其划时代的Netware/86网络套件时采用的私有以太网帧格式,该格式以当时尚未正式发布的802.3标准为基础;但是当两年以后IEEE正式发布802.3标准时情况发生了变化—IEEE在802.3帧头中又加入了802.2 LLC(Logical Link Control)头,这使得Novell的RAW 802.3格式跟正式的IEEE 802.3标准互不兼容;可以看到在Novell的RAW 802.3帧结构中并没有标志协议类型的字段,而只有Length 字段(2bytes,取值为0000-05dc,即十进制的0-1500),因为RAW 802.3帧只支持IPX/SPX一种协议;

4 Ethernet 802.3 SAP帧格式

这种帧格式属于 IEEE 802.3/802.2 LLC 标准。

在Ethernet 802.3 SAP帧中,将原Ethernet 802.3 raw帧中2个字节的0xFFFF变为各1个字节的DSAP和SSAP,同时增加了1个字节的”控制”字段,构成了802.2逻辑链路控制(LLC)的首部。LLC提供了无连接(LLC类型1)和面向连接(LLC类型2)的网络服务。LLC1是应用于以太网中,而LLC2应用在IBM SNA网络环境中。

新增的802.2 LLC首部包括两个服务访问点:源服务访问点(SSAP)和目标服务访问点(DSAP)。它们用于标识以太网帧所携带的上层数据类型,如16进制数0x06代表IP协议数据,16进制数0xE0代表Novell类型协议数据,16进制数0xF0代表IBM NetBIOS类型协议数据等。

常见SAP值:

  • 0 Null LSAP

  • 4 SNA Path Control

  • 6 DOD IP

  • AA: SNAP

  • FE: ISO DIS

  • FF: Global DSAP

……

SAP值用以标志上层应用,但是每个SAP字段只有8bits长,而且其中仅保留了6比特用于标识上层协议,因此所能标识的协议数有限(不超过32种);并且IEEE拒绝为某些重要的协议比如ARP协议定义SAP值(奇怪的是同时他们却定义了IP的SAP值);因此802.3/802.2 LLC的使用有很大局限性;

至于1个字节的”控制”字段,则基本不使用(一般被设为0x03,指明采用无连接服务的802.2无编号数据格式)。

5 Ethernet 802.3 SNAP帧格式

Ethernet 802.3 SNAP类型以太网帧格式和Ethernet 802.3 SAP类型以太网帧格式的主要区别在于:

  • 2个字节的DSAP和SSAP字段内容被固定下来,其值为16进制数0xAA。

  • 1个字节的”控制”字段内容被固定下来,其值为16进制数0x03。

  • 增加了SNAP字段,由下面两项组成

    • 新增了3个字节的组织唯一标识符(Organizationally Unique Identifier,OUI ID)字段,其值通常等于MAC地址的前3字节

    • 增加了表示上层协议的类型

这是IEEE为保证在802.2 LLC上支持更多的上层协议同时更好的支持IP协议而发布的标准,与802.3/802.2 LLC一样,802.3/802.2 SNAP也带有LLC头,但是扩展了LLC属性,新添加了一个2Bytes的协议类型域(同时将SAP的值置为AA),从而使其可以标识更多的上层协议类型;另外添加了一个3Bytes的OUI字段用于代表不同的组织,RFC 1042定义了IP报文在802.2网络中的封装方法和ARP协议在802.2 SANP中的实现;

一点资料

关于802.3 的标准,历史真是晦暗不明,看wiki都看不出个所以然来,我只能简单列举一下资料:

https://en.wikipedia.org/wiki/Ethernet_frame#Novell_raw_IEEE_802.3

http://lostintransit.se/2012/06/06/the-history-of-ethernet-dix-vs-802-3/

一点小tip

Q: MTU最大可以设置为多大?

A: 9000,这是由CRC校验的能力决定的。参考:

https://en.wikipedia.org/wiki/Jumbo_frame

PS:早期的一些网络,比如超通道,可以支持65535的mtu,但是已经湮没于历史风尘中了。

参考:

https://zh.wikipedia.org/wiki/IEEE_802.1ad

https://en.wikipedia.org/wiki/Ethernet_frame