0%

这次新平台采用了与之前不同的以太网方案, MAC是内置在SoC(System On Chip)上,而PHY采用了Marvell的一款100Mps的车规级的芯片,MAC/PHY的驱动都要重新开发适配,工作难度比之前预想的要大了很多,完成时间比预想的慢了近一个星期。不过,往后看,这种直接与硬件打交道的经验很能锻炼人,在一定程度改善了我对系统的认知与理解。这篇文章重点在梳理总结下车在以太网MAC/PHY遇到的一些问题,以及Linux下MAC/PHY驱动的一些基本流程。

大致分为如下几个部分:

  • MAC/PHY的基础知识
  • Linux下MAC/PHY驱动的加载流程
  • PHY驱动的开发与适配
  • 车载以太网MAC/PHY调试的一些经验总结
阅读全文 »

汽车电子的发展伴随着技术迭代而不断进化,汽车网络总线从最开的CAN,CAN-FD,到后来的Flexray, MOST再到LIN,到Ethernet,在市场需求与技术发展双重合力之下,经过了不断的发展积累,到如今已经有进40年的历史。近几年,随着各大汽车公司,尤其是新能源汽车公司如特斯拉/蔚来/小鹏等在自动驾驶领域的大力投入,汽车网络开始向高带宽/低延时的以太网方向发展。在这篇文章我们就来对比看看各种汽车网络总线的工作原理以及使用场景。

CAN(Controller Area Network)

CAN最初是由博世(Bosch)于1985年开发出来的车内总线。在这之前,汽车厂商需要通过一条条线将各种汽车控制器连接起来,形成一个个点对点的连接网络。这也导致了增加了汽车本身的重量,增加了系统的复杂度与成本。

CAN作为一个串行总线,具有低成本,轻量化的优势,最高支持1Mb/s的速率,因此迅速被各大厂商采用,并于1993年被定为ISO国际化标准(ISO 11898).

阅读全文 »

在看Linux内核代码时,经常会遇到各种锁(lock)的使用。对于像spin_lock_irq/spin_lock_irqsave的区别感到困惑,每次都要重新查一下资料。遂决定写一篇文章记录下内核中使用到的锁,以及使用的场景。

与应用中的锁类似,内核中的锁也只是为了保护某个内核数据结构或者内存区域在多个执行路径时不被破坏,确保数据的一致性。Linux内核作为应用层服务的提供者,一方面要为应用提供系统调用接口(system call),代表用户进程执行任务,即process context;同时与硬件直接交互,要响应硬件中断的请求,处理诸如网卡数据/串口数据等请求,即Interrupt Context. 内核就是在进程上下文/中断上下文直接来回切换,执行相应的任务请求。这就自然产生了数据的并发访问,产生了竞争条件(race condition)。另一方面,目前大多数的系统都是多核CPU的,多个CPU同时访问内核数据也同样会产生竞争条件。

阅读全文 »

最近新的项目又开始了, 开始还算顺利, 却不料碰到了一个奇怪的问题. 先来了解下问题的背景. 这个项目里, Android中有两个以太网网口, 一个用于内网通讯, 不具备上外网的能力;一个用于外网通讯, 使用该网口可以访问互联网. 在网络管理模块的工作完成后, 提交了代码我原本以为可以高枕无忧, 前两天组内的同学跑过来告诉我, 他有个系统服务一直没法通过与内网的其他设备上的服务建立TCP链接, 但是网络却一直可以ping通; 而另外的一个开发板上却不存在这个问题.

开始我有点不相信竟然会有这样的问题, 但事实摆在面前, 我也不好抵赖, 于是自己找来一个板子, 看了下, 才逐渐找到答案. 问题的根源在于Android配置的策略路由规则隐含了一个针对系统默认网络的fwmark规则, 要解决问题, 只要我们将包含了内网路由表的路由规则的优先级提升到高于Android隐含的这条规则即可. 虽然找到了解决方案, 但是还是决定花点时间把整个事情的来龙去脉都理清楚.

大致分如下几个部分来讲一讲这个问题:

  • 介绍下什么是Policy Routing<策略路由>
  • 分析具体的问题, 并给出方案
  • 从源代码角度来分析下, 为何TCP无法建立, 但ping却可以
阅读全文 »

Excellence in any department can be attained only by the labor of a lifetime;it is not to be purchased at a lesser price

Paul Graham

前段时间, 看新闻说“微软4万多的软件开发工程师, 每天产生进3万个BUG”, 当时感觉有点震惊, 然后就哑然失笑. 震惊的是连微软这样厉害的公司, 工程师应该都很优秀, 人才济济, 为何却会每天产生这么多的BUG了? 于是,再想想自己的开发经历, 才恍然明白: 开发人员一旦走进办公室,打开电脑写代码, 就不可避免的要写出BUG来. 与BUG纠缠不清似乎是每个开发人员的宿命.恰逢最近遇到了一个BUG, 让我纠结不已, 痛定思痛, 觉得有必要把自己的开发”心得经验”写下来, 权当是给自己一点警醒, 给自己一点回顾的资料, 分享下自己在开发过程中遇到的困难与挫折, 苦恼与迷惑.

阅读全文 »

NAPI(New API)是Linux内核针对网络数据传输做出的一个优化措施,其目的是在高负载的大数据传输时,网络驱动收到硬件中断后,通过poll(轮询)方式将传输过来的数据包统一处理, 在poll时通过禁止网络设备中断以减少硬件中断数量(Interrupt Mitigation),从而实现更高的数据传输速率。

基于NAPI接口, 一般的网络传输(接收)有如下几个步骤:

  • 网络设备驱动加载与初始化(配置IP等)
  • 数据包从网络侧发送到网卡(Network Interface Controller, NIC)
  • 通过DMA(Direct Memory Access),将数据从网卡拷贝到内存的环形缓冲区(ring buffer)
  • 数据从网卡拷贝到内存后, NIC产生硬件中断告知内核有新的数据包达到
  • 内核收到中断后, 调用相应中断处理函数, 此时就会调用NAPI接口__napi_schedule开启poll线程(实际是触发一个软中断NET_RX_SOFTIRQ)(常规数据传输, 一般在处理NIC的中断时调用netif_rx_action处理网卡队列的数据)
  • ksoftirqd(每个CPU上都会启动一个软中断处理线程)收到软中断后被唤醒, 然后执行函数net_rx_action, 这个函数负责调用NAPI的poll接口来获取内存环形缓冲区的数据包
  • 解除网卡ring buffer中的DMA内存映射(unmapped), 数据由CPU负责处理, netif_receive_skb传递回内核协议栈
  • 如果内核支持数据包定向分发(packet steering)或者NIC本身支持多个接收队列的话, 从网卡过来的数据会在不同的CPU之间进行均衡, 这样可以获得更高的网络速率
  • 网络协议栈处理数据包,并将其发送到对应应用的socket接收缓冲区
阅读全文 »

使用Android手机时, 我们不仅可以看到当前系统的流量使用情况, 还可以查看每个应用消耗了多少流量, 借此我们可以发现有那些流氓APP在偷偷在背后消耗流量.那么, Android是具体如何实现流量统计的? 又是如何对每个应用的流量使用进行监控? 这篇文章我们就来看看Android流量统计的具体实现原理.

大致说来, Android从如何几个方面进行流量统计:

  • 统计每个网口当前发送/接收的流量数据
  • 监控每个应用(对应唯一的UID)所消耗的流量
  • 支持对总的流量配额进行限制, 如达到一定的流量阈值后, 会对网络进行限制

而具体到每个应用(比如system应用, UID=1000), Android还支持对应用内的每个socket进行标记(tag), 用于区分每个应用(UID)内部具体使用了那些流量.后面, 我们会讲到如何通过标签来区分UID内部的流量.

阅读全文 »

SSH(Secure SHell)是一种基于加密算法的网络安全协议, 其在TCP/IP协议的基础上通过非对称公钥算法对用户身份进行验证. SSH在网络中有广泛的应用, 比如平常在远程登录时就会用到SSH, Github的代码仓库提交也会基于SSH协议来验证提交者的合法性, 而对常年生活在局域网内的人来说, SSH更多的用途则是搭建穿越防火墙的VPN实现网络自由.

一台服务器如果有公共域名或者IP地址, 只需要事先将客户端的公钥放到服务器上就可以正常登录, 但如果服务器本身位于防火墙之外(比如某个端口被禁)或者位于NAT(Network Address Translation)网关之后, 这个方法就不起作用了. 用过VPN的同志应该比较清楚, 穿透防火墙或者某个局域网的NAT网关, 一般要用到SSH隧道技术(SSH tunneling);SSH隧道技术也被称为端口转发(port forwarding).简单来说, 建立SSH隧道大致有两个流程:

阅读全文 »