OpenHarmony设备开发标准系统内核(Linux) 内核增强特性

zh_ff
发布于 2023-4-14 16:15
浏览
0收藏

Enhanced SWAP特性介绍

基本概念

ESwap(Enhanced Swap)提供了自定义新增存储分区作为内存交换分区的能力,并创建了一个常驻进程zswapd将​​ZRAM​​压缩后的匿名页加密换出到ESwap存储分区,从而能完全的空出一块可用内存,以此来达到维持Memavailable水线的目标。同时,配合这个回收机制,在整个内存框架上进行改进,优化匿名页和文件页的回收效率,并且使两者的回收比例更加合理以避免过度回收导致的refault问题造成卡顿现象。

ZRAM与ESwap配置指导

说明:

 使能ESwap需要在使能ZRAM之前,不需要使用ESwap时, 也可以仅使能ZRAM。如部分设备不包括用于换出的存储设备,也没有新建相应的存储分区,那么可以仅使能ZRAM来通过zswapd进行内存回收。

使能ESwap
  1. 打开相关配置项及依赖。
    启用ESwap,需要通过编译内核时打开相应的配置项及依赖,ESwap相关CONFIG如下:

CONFIG_HYPERHOLD=y                  // Enable HyperHold
CONFIG_HYPERHOLD_DEBUG=y            // Enable HyperHold Debug
CONFIG_HYPERHOLD_ZSWAPD=y           // Enable zswapd thread to reclaim anon pages in background
CONFIG_HYPERHOLD_FILE_LRU=y         // Enable HyperHold FILE LRU
CONFIG_HYPERHOLD_MEMCG=y            // Enable Memcg Management in HyperHold
CONFIG_ZRAM_GROUP=y                 // Enable Manage Zram objs with mem_cgroup
CONFIG_ZRAM_GROUP_DEBUG=y           // Enable Manage Zram objs with mem_cgroup Debug
CONFIG_ZLIST_DEBUG=y                // Enable Debug info for zram group list
CONFIG_ZRAM_GROUP_WRITEBACK=y       // Enable Write back grouped zram objs to Hyperhold driver

同时,开启ESwap需依赖以下CONFIG:

CONFIG_MEMCG=y       // Enable Memory controller
CONFIG_SWAP=y        // Enable Support for paging of anonymous memory (swap)
CONFIG_ZSMALLOC=y    // Enable Memory allocator for compressed pages
CONFIG_ZRAM=y        // Enable Compressed RAM block device support

2.创建ESwap设备。
可以使用任意block设备作为ESwap交换设备,这里创建一个文件hpdisk挂载为loop6设备:

// 通过dd命令创建一个文件hpdisk用于ESwap换出,具体大小需根据产品及需求调整,此处设置为512MB。
dd if=/dev/random of=/data/hpdisk bs=4096 count=131072
// 将上一步创建的hpdisk与ESwap device进行绑定。
losetup /dev/block/loop6 hpdisk
    Bash

3.配置ESwap。
将2中创建的设备绑定为ESwap换出设备:

echo /dev/block/loop6 > /proc/sys/kernel/hyperhold/device
    Bash

ESwap默认对换出数据使用软件加密,如果2中创建的ESwap设备支持inline加密,可以关闭ESwap的软件加密功能:

// 需咨询开发板厂商是否支持并开启硬加密,否则不要执行该操作。
echo 0 > /proc/sys/kernel/hyperhold/soft_crypt
    Bash

 

注意:

 出于安全考虑,所有换出内容均需加密。因此若当前配置ESwap的设备不支持inline加密,或编译时未打开inline加密宏,则在关闭软加密时,ESwap无法enable。

4.使能ESwap。
使能ESwap,使能后无法更改上述配置:

echo enable > /proc/sys/kernel/hyperhold/enable
    Bash
使能ZRAM
  1. 初始化ZRAM。
    设置ZRAM与ESwap的交互方式,并配置ZRAM的大小。

// 打开ZRAM到ESwap的换入换出功能,该步骤必须要在配置ZRAM大小之前。
echo readwrite > /sys/block/zram0/group
// 配置ZRAM的大小,具体大小需根据产品及需求调整,此处设置为512MB。
echo 512M > /sys/block/zram0/disksize
    Bash


说明:

 /sys/block/zram0/group可接受参数及作用为:

  • disable:表示禁用;
  • readonly:表示只记录数据的cgroup信息,并不换出;
  • readwrite:表示打开ZRAM到eswap的换入换出功能。

2.使能ZRAM。
启用ZRAM设备为交换分区并将其使能。

mkswap /dev/block/zram0
swapon /dev/block/zram0
    Bash
关闭ESwap与ZRAM
  1. 关闭ESwap。

echo disable > /proc/sys/kernel/hyperhold/enable
或
echo force_disable > /proc/sys/kernel/hyperhold/enable
    Bash

 

说明:

 两者的区别在于:

  • disable:表示如果ESwap中没有数据,则完全关闭,否则变为只读模式;
  • force_disable:表示如果没有数据,完全关闭,否则变为只读模式,并同步等待ESwap中数据完全读出,然后完全关闭。

2.关闭ZRAM及ZRAM group。

// 若已经执行过swapon,则需先执行swapoff
swapoff /dev/block/zram0
echo 1 > /sys/block/zram0/reset
    Bash

ESwap相关接口

ESwap提供了一些接口用于控制换入换出策略以及记录当前状态,这些接口位于memcg所挂载的目录当中,如​​/dev/memcg/​​。

功能分类

接口名

描述

参考值

控制接口

​avail_buffers​

设置buffer区间

300 250 350 200

​zswapd_single_memcg_param​

设置当前memcg相关配置

300 40 0 0

​zram_wm_ratio​

设置zram换出水线

0

状态接口

​zswapd_pressure_show​

记录当前buffer以及refault

NA

​stat​

检测ESwap实时情况

NA

​zswapd_vmstat_show​

记录zswapd运行过程中各种事件

NA

 

注意:

 除avail_buffers会因为调整了buffer水线而会主动去唤醒zswapd外,其余控制接口并不会主动唤醒zswapd,只是其配置需在zswapd所被唤醒后方可生效。

avail_buffers

avail_buffers接口用于设置buffer区间[min_avail_buffers, high_avail_buffers],当检测到当前的buffer低于min_avail_buffers时则会唤醒zswapd进行匿名页回收,期望的回收量为high_avail_buffers与当前系统buffer值的差值,实际可能会因为无法回收等原因而未回收足够多内存。avail_buffers为期望的内存正常状态buffer值,free_swap_threshold则是设置交换分区空闲容量的阈值,当zswapd唤醒并进行内存回收之后,会根据当前系统情况以及两者的设置记录当前内存压力事件,如medium press,critical press等。可主动调整来触发zswapd回收,如​​echo 1000 950 1050 0 > /dev/memcg/memory.avail_buffers​​。

默认值:

avail_buffers: 0
min_avail_buffers: 0
high_avail_buffers: 0
free_swap_threshold: 0

限制:

0<=min_avail_buffers<=avail_buffers<=high_avail_buffers

0<=free_swap_threashold

取值均为整型。

zswapd_single_memcg_param

设置当前memcg的相关配置。score为当前memcg回收优先级,ub_mem2zram_ratio为内存压缩到ZRAM的比率,ub_zram2ufs_ratio为ZRAM换出到ESwap的比率,refault_threshold为refault的阈值,可通过调整比率来控制ZRAM压缩以及ESwap换出情况,如​​echo 60 10 50 > memory.zswapd_single_memcg_param​​。

默认值:

memcg score: 300
memcg ub_mem2zram_ratio: 60
memcg ub_zram2ufs_ratio: 10
memcg refault_threshold: 50

限制:

0<=ub_mem2zram_ratio<=100

0<=ub_zram2ufs_ratio<=100

0<=refault_threshold<=100

取值均为整型。

zram_wm_ratio

设置ZRAM换出水线,即当当前ZRAM中压缩的匿名页大于ZRAM总大小*zram_wm_ratio时,会开始向ESwap进行换出,但是具体换出时间为zswapd因buffer水线而唤醒之后。设置为0时系统默认为37,可进行调整,如​​echo 30 > /dev/memcg/memory.zram_wm_ratio​​。

默认值:

zram_wm_ratio: 0

限制:

0<=zram_wm_ratio<=100

取值为整型。

zswapd_pressure_show

记录当前zswapd所需相关状态,buffer_size为当前系统的buffer值,recent_refault为最近产生的refault次数。

stat

在原有memcg.stat的基础上新增了Anon,File,zram,Eswap等项,用以监测ESwap的实时情况。

zswapd_vmstat_show

记录zswapd运行过程中的各种事件。

触发zswapd回收

可先通过​​cat /dev/memcg/memory.zswapd_pressure_show​​查看当前buffer值,比如当前为1200,那么可通过主动调整buffer区间大于1200,来主动唤醒zswapd。

echo 1300 1250 1350 0 > /dev/memcg/memory.avail_buffers
    Bash

ESwap配置大小示例

ZRAM与ESwap的大小配置需根据实际使用场景以及产品硬件特点进行适配。目前在rk3568板子上使用时,其ram为2G,因此设置的ZRAM与ESwap大小均为512MB。

New IP内核协议栈介绍

基本概念

New IP在现有IP能力的基础上,以灵活轻量级报头和可变长多语义地址为基础,通过二三层协议融合,对协议去冗和压缩,减少冗余字节,实现高能效比,高净吞吐,提升通信效率。打造终端之间高效的横向通信,支撑超级终端的体验,实现异构网络的端到端互联。

目前WiFi协议报文,三层报头和地址开销使得报文开销大,传输效率较低。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

IPv4地址长度固定4字节,IPv6地址长度固定16字节。
IPv4网络层报头长度20~60字节,IPv6网络层报头长度40字节。

New IP支持可变长多语义地址(最短1字节)可变长定制化报头封装(最短5字节),通过精简报文头开销,提升数据传输效率。

New IP报头开销,相比IPv4节省25.9%,相比IPv6节省44.9%。

New IP载荷传输效率,相比IPv4提高最少1%,相比IPv6提高最少2.33%。

对比场景

报头开销

载荷传输效率(WiFi MTU=1500B,BT MTU=255B)

IPv4 for WiFi

30+8+20=58 B

(1500-58)/1500=96.13%

IPv6 for WiFi

30+8+40=78 B

(1500-78)/1500=94.8%

New IP for WiFi

30+8+5=43 B

(1500-43)/1500=97.13%

可变长报头格式

New IP WiFi灵活极简报文头如下图所示,通过LLC Header中的EtherType = 0xEADD标识New IP报文。Bitmap是一组由0和1组成的二进制序列,每个二进制位的数值用于表示New IP报头中是否携带某个字段,即New IP报文头可以由用户根据业务场景自行定制报头中携带哪些字段。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

  1. Dispatch:指示封装子类,数值0b0表示其为极简封装子类,长度为1比特;(0b表示后面数值为二进制)。
  2. Bitmap:变长,Bitmap默认为紧跟在Dispatch有效位后面的7比特,Bitmap字段长度可持续扩展。Bitmap最后一位置0表示Bitmap结束,最后一位置1表示Bitmap向后扩展1 Byte,直至最后一位置0。
  3. Value: 标识字段的值,长度为1 Byte的整数倍,类型及长度由报头字段语义表确定。

Bitmap字段定义如下:

极简Bitmap标识

Bitops

携带字段的长度

置位策略

备注

Bitmap 1st Byte:

-

-

-

下面8bit是从高位到低位排列。

标记位Dispatch

0

-

置0

0:极简封装报头,1:非极简封装报头。

报文头是否携带TTL

1

1 Byte

置1

剩余跳数。

报文头是否携带Total Length

2

2 Byte

UDP置0,TCP置1

New IP报文总长度(包含报头长度)。

报文头是否携带Next Header

3

1 Byte

置1

协议类型。

Reserve

4

保留

置0

保留字段。

报文头是否携带Dest Address

5

变长(1~8 Byte)

置1

目的地址。

报文头是否携带Source Address

6

变长(1~8 Byte)

由协议自行确定

源地址。

标记位,标志是否有2nd Byte

7

-

-

0:bitmap结束,1:后跟另外8bit bitmap。

Bitmap 2nd Byte:

-

-

-

下面8bit是从高位到低位排列。

报文头是否携带Header Length

0

1 Byte

-

New IP报头长度。

Reserve

1

保留

置0

-

Reserve

2

保留

置0

-

Reserve

3

保留

置0

-

Reserve

4

保留

置0

-

Reserve

5

保留

置0

-

Reserve

6

保留

置0

-

标记位,标志是否有3rd Byte

7

-

-

0:bitmap结束,1:后跟另外8bit bitmap。

New IP报头(极简封装)解析遇到新bitmap字段时的处理方法:

仅解析当前版本协议中已定义的bitmap字段,从第一个未知语义的bitmap字段开始,跳过后面的所有bitmap字段,直接通过header length定位到报文开始位置并解析报文。如果报头中携带了未知语义的bitmap字段,且未携带header length字段,则丢弃该数据包。

可变长地址格式

New IP支持可变长地址(IPv4/IPv6地址长度固定),支持自解析地址长度,报文头中可以不携带地址长度字段,New IP地址编码格式如下所示:

First Byte

Semantics

地址段有效范围

0x00

Address is 0

【1字节】0 ~ 220 (0x00 ~ 0xDC)

0x01

Address is 1

-

0x02

Address is 2

-

-

0xDC

Address is 220

-

0xDD

An 16-bit address, which is 0 + 256 * (0xDD - 0xDD) + the last byte value

【2字节】221 ~ 255 (0xDDDD ~ 0xDDFF)

0xDE

An 16-bit address, which is 0 + 256 * (0xDE - 0xDD) + the last byte value

【2字节】256 ~ 511 (0xDE00 ~ 0xDEFF)

0xDF

An 16-bit address, which is 0 + 256 * (0xDF - 0xDD) + the last byte value

【2字节】512 ~ 767 (0xDF00 ~ 0xDFFF)

-

0xF0

An 16-bit address, which is 0 + 256 * (0xF0 - 0xDD) + the last byte value

【2字节】4864 ~ 5119 (0xF000 ~ 0xF0FF)

0xF1

An 16-bit address is followed

【3字节】5120 ~ 65535 (0xF1 1400 ~ 0xF1 FFFF)

0xF2

An 32-bit address is followed

【5字节】65536 ~ 4,294,967,295 (0xF2 0001 0000 ~ 0xF2 FFFF FFFF)

0xF3

An 48-bit address is followed

【7字节】4,294,967,296 ~ 281,474,976,710,655 (0xF3 0001 0000 0000 ~ 0xF3 FFFF FFFF FFFF)

0xFE

An 56-bit address is followed

【8字节】0 ~ 72,057,594,037,927,935 (0xFE00 0000 0000 0000 ~ 0xFEFF FFFF FFFF FFFF)

New IP配置指导

New IP使能

目前只有rk3568开发板Linux 5.10内核上支持New IP内核协议栈,在rk3568开发板内核模块配置文件中搜索NEWIP,将其修改成“CONFIG_XXX=y”即可,New IP相关CONFIG如下。

# kernel/linux/config/linux-5.10/arch/arm64/configs/rk3568_standard_defconfig
CONFIG_NEWIP=y          // 使能New IP内核协议栈
CONFIG_NEWIP_HOOKS=y    // 使能New IP内核侵入式修改插桩函数注册,使能New IP的同时必须使用New IP HOOKS功能
VENDOR_HOOKS=y          // 使能内核插桩基础框架(New IP依赖此配置项,rk3568开发板已默认开启)

代码编译完成后,通过下面命令可以确认New IP协议栈代码是否使能成功。

find out/ -name *nip*.o
...
out/kernel/OBJ/linux-5.10/net/newip/nip_addrconf_core.o
out/kernel/OBJ/linux-5.10/net/newip/nip_hdr_decap.o
out/kernel/OBJ/linux-5.10/net/newip/nip_addr.o
out/kernel/OBJ/linux-5.10/net/newip/nip_checksum.o
out/kernel/OBJ/linux-5.10/net/newip/tcp_nip_output.o
...

备注:OpenHarmony linux内核要求所有原生内核代码侵入式修改,都要修改成插桩方式。例如下面IPv4,IPv6协议栈公共流程中增加New IP处理时,不能直接调用New IP函数,需要在公共流程中增加插桩点,New IP使能后在模块初始化时将xx功能函数注册到对应的函数指针上,下面公共流程就可以通过函数指针的形式调用到New IP的函数。

/* 将New IP ehash函数注册到内核 */
register_trace_ninet_ehashfn_hook(&ninet_ehashfn_hook, NULL);


/* 下面是IPv4,IPv6协议栈总入口函数,在总入口函数内新增New IP协议栈相关处理 */
static u32 sk_ehashfn(const struct sock *sk)
{
    /* IPv6 */
#if IS_ENABLED(CONFIG_IPV6)if (sk->sk_family == AF_INET6 &&
	    !ipv6_addr_v4mapped(&sk->sk_v6_daddr))
		return inet6_ehashfn(sock_net(sk),
				     &sk->sk_v6_rcv_saddr, sk->sk_num,
				     &sk->sk_v6_daddr, sk->sk_dport);
#endif

#if IS_ENABLED(CONFIG_NEWIP_HOOKS)if (sk->sk_family == AF_NINET) {
		u32 ret = 0;

        /* New IP注册的ehash函数 */
		trace_ninet_ehashfn_hook(sock_net(sk), &sk->sk_nip_rcv_saddr, sk->sk_num,
					 &sk->sk_nip_daddr, sk->sk_dport, &ret);
		return ret;
	}
#endif

    /* IPv4 */return inet_ehashfn(sock_net(sk),
			    sk->sk_rcv_saddr, sk->sk_num,
			    sk->sk_daddr, sk->sk_dport);
}
    c
New IP禁用

在rk3568开发板内核模块配置文件中搜索NEWIP,将其“CONFIG_NEWIP=y”和“CONFIG_NEWIP_HOOKS=y”删除或使用#注释掉即可。

# kernel/linux/config/linux-5.10/arch/arm64/configs/rk3568_standard_defconfig
# CONFIG_NEWIP is not set
# CONFIG_NEWIP_HOOKS is not set

New IP相关接口

用户态应用程序调用Socket API创建New IP socket,采用New IP极简封装进行收发包,New IP协议socket接口列表如下:

函数

输入

输出

返回值

接口具体描述

socket

int domain, int type, int protocol

NA

Socket句柄sockfd

创建New IP 协议类型socket,并返回socket实例所对应的句柄。domain参数填写 AF_NINET,表示创建New IP协议类型socket。protocol参数填写IPPROTO_TCP或IPPROTO_UDP

bind

int sockfd, const struct sockaddr_nin *myaddr, socklen_t addrlen

NA

int,返回错误码

将创建的socket绑定到指定的IP地址和端口上。myaddr->sin_family填写AF_NINET

listen

int socket, int backlog

NA

int,返回错误码

服务端监听New IP地址和端口。

connect

int sockfd, const struct sockaddr_nin *addr, aocklen_t addrlen

NA

int,返回错误码

客户端创建至服务端的连接。

accept

int sockfd, struct sockaddr_nin *address, socklen_t *address_len

NA

返回socket的fd

服务端返回已建链成功的socket。

send

int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr_nin *dst_addr, int addrlen

NA

int,返回错误码

用于socket已连接的New IP类型数据发送。

recv

int sockfd, size_t len, int flags, struct sockaddr_nin *src_addr,

void *buf, int *fromlen

int,返回错误码

用于socket已连接的New IP类型数据接收。

close

int sockfd

NA

int,返回错误码

关闭socket,释放资源。

ioctl

int sockfd, unsigned long cmd, …

NA

int,返回错误码

对New IP协议栈相关信息进行查询或更改。

sendto

int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *dst_addr, int addrlen

NA

int,返回错误码

用于socket无连接的New IP类型数据发送。

recvfrom

int sockfd, size_t len, int flags,

void *buf, struct sockaddr *from, int *fromlen

int,返回错误码

用于socket无连接的New IP类型数据接收。

New IP短地址结构如下:

enum nip_8bit_addr_index {
	NIP_8BIT_ADDR_INDEX_0 = 0,
	NIP_8BIT_ADDR_INDEX_1 = 1,
	NIP_8BIT_ADDR_INDEX_2 = 2,
	NIP_8BIT_ADDR_INDEX_3 = 3,
	NIP_8BIT_ADDR_INDEX_4 = 4,
	NIP_8BIT_ADDR_INDEX_5 = 5,
	NIP_8BIT_ADDR_INDEX_6 = 6,
	NIP_8BIT_ADDR_INDEX_7 = 7,
	NIP_8BIT_ADDR_INDEX_MAX,
};

enum nip_16bit_addr_index {
	NIP_16BIT_ADDR_INDEX_0 = 0,
	NIP_16BIT_ADDR_INDEX_1 = 1,
	NIP_16BIT_ADDR_INDEX_2 = 2,
	NIP_16BIT_ADDR_INDEX_3 = 3,
	NIP_16BIT_ADDR_INDEX_MAX,
};

enum nip_32bit_addr_index {
	NIP_32BIT_ADDR_INDEX_0 = 0,
	NIP_32BIT_ADDR_INDEX_1 = 1,
	NIP_32BIT_ADDR_INDEX_MAX,
};

#define nip_addr_field8 v.u.field8
#define nip_addr_field16 v.u.field16
#define nip_addr_field32 v.u.field32

#pragma pack(1)
struct nip_addr_field {
	union {
		unsigned char   field8[NIP_8BIT_ADDR_INDEX_MAX];
		unsigned short field16[NIP_16BIT_ADDR_INDEX_MAX]; /* big-endian */unsigned int   field32[NIP_32BIT_ADDR_INDEX_MAX]; /* big-endian */
	} u;
};

struct nip_addr {
	unsigned char bitlen;	/* The address length is in bit (not byte) */struct nip_addr_field v;
};
#pragma pack()

/* The following structure must be larger than V4. System calls use V4.
 * If the definition is smaller than V4, the read process will have memory overruns
 * v4: include\linux\socket.h --> sockaddr (16Byte)
 */
#define POD_SOCKADDR_SIZE 3
struct sockaddr_nin {
	unsigned short sin_family; /* [2Byte] AF_NINET */unsigned short sin_port;   /* [2Byte] Transport layer port, big-endian */struct nip_addr sin_addr;  /* [9Byte] NIP address */

	unsigned char sin_zero[POD_SOCKADDR_SIZE]; /* [3Byte] Byte alignment */
};
    c

New IP开发说明

目前只在OpenHarmony Linux-5.10内核支持New IP内核协议栈,只能在用户态人工配置New IP地址和路由到内核,两台设备通过路由器WiFi连接。如果想配置New IP地址和路由后自动切换到New IP内核协议栈通信,应用可以参考下面蓝框中描述。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

上图中New IP地址,路由配置程序可以参考​​代码仓examples代码​​,根据CPU硬件差异更改Makefile中CC定义编译成二级制文件后推送到开发板,参考上图命令给设备配置New IP地址和路由。

文件名

功能

nip_addr.c

New IP可变长地址配置demo代码(可配置任意有效New IP地址)

nip_route.c

New IP路由配置demo代码(可配置任意有效New IP地址)

check_nip_enable.c

获取本机New IP能力

设备1上查看New IP地址和路由:

# cat /proc/net/nip_addr
01          wlan0
# cat /proc/net/nip_route
02      ff09       1 wlan0        # 到设备2的路由
01      01      2149580801 wlan0  # 本机自发自收路由    sh

设备2上查看New IP地址和路由:

# cat /proc/net/nip_addr
02          wlan0
# cat /proc/net/nip_route
01      ff09       1 wlan0        # 到设备1的路由
02      02      2149580801 wlan0  # 本机自发自收路由    sh

New IP收发包代码示例

New IP可变长地址配置,路由配置,UDP/TCP收发包demo代码链接如下,New IP协议栈用户态接口使用方法可以参考​​代码仓examples代码​​。demo代码内配置固定地址和路由,执行编译后二进制程序时不需要人工指定地址和路由。

文件名

功能

nip_addr_cfg_demo.c

New IP可变长地址配置demo代码

nip_route_cfg_demo.c

New IP路由配置demo代码

nip_udp_server_demo.c

New IP UDP收发包服务端demo代码

nip_udp_client_demo.c

New IP UDP收发包客户端demo代码

nip_tcp_server_demo.c

New IP TCP收发包服务端demo代码

nip_tcp_client_demo.c

New IP TCP收发包客户端demo代码

nip_lib.c

接口索引获取等API接口demo代码

基础操作步骤:

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

  1. 将demo代码拷贝到Linux编译机上,make clean,make all编译demo代码。
  2. 将编译生成二级制文件上传到设备1,设备2。
  3. 执行“ifconfig wlan0 up”开启网卡设备。
  4. 在设备1的shell下执行“./nip_addr_cfg_demo server”给服务端配置0xDE00(2字节)变长地址,在设备2的shell下执。行“./nip_addr_cfg_demo client”给客户端配置0x50(1字节)变长地址,通过“cat /proc/net/nip_addr”查看内核地址配置结果。
  5. 在设备1的shell下执行“./nip_route_cfg_demo server”给服务端配置路由,在设备2的shell下执行“./nip_route_cfg_demo client”给客户端配置路由,通过“cat /proc/net/nip_route”查看内核路由配置结果。

以上步骤操作完成后,可以进行UDP/TCP收发包,收发包demo默认使用上面步骤中配置的地址和路由。

UDP收发包操作步骤:

先在服务端执行“./nip_udp_server_demo”,然后再在客户端执行“./nip_udp_client_demo”,客户端会发送10个New IP报文,服务端收到报文后再发送给客户端。

服务端shell窗口打印内容:
Received -- 1661826989 498038 NIP_UDP #      0 -- from 0x50:57605
Sending  -- 1661826989 498038 NIP_UDP #      0 -- to 0x50:57605
Received -- 1661826990  14641 NIP_UDP #      1 -- from 0x50:57605
Sending  -- 1661826990  14641 NIP_UDP #      1 -- to 0x50:57605
Received -- 1661826990 518388 NIP_UDP #      2 -- from 0x50:57605
Sending  -- 1661826990 518388 NIP_UDP #      2 -- to 0x50:57605
...
Received -- 1661827011 590576 NIP_UDP #      9 -- from 0x50:37758
Sending  -- 1661827011 590576 NIP_UDP #      9 -- to 0x50:37758

客户端sh窗口打印内容:
Received --1661827007  55221 NIP_UDP #      0 sock 3 success:     1/     1/no=     0
Received --1661827007 557926 NIP_UDP #      1 sock 3 success:     2/     2/no=     1
Received --1661827008  62653 NIP_UDP #      2 sock 3 success:     3/     3/no=     2
...
Received --1661827011 590576 NIP_UDP #      9 sock 3 success:    10/    10/no=     9

TCP收发包操作步骤:

先在服务端执行“./nip_tcp_server_demo”,然后再在客户端执行“./nip_tcp_client_demo”,客户端会发送10个New IP报文,服务端收到报文后再发送给客户端。

服务端shell窗口打印内容:
Received -- 1661760202 560605 NIP_TCP #      0 --:1024
Sending  -- 1661760202 560605 NIP_TCP #      0 --:1024
Received -- 1661760203  69254 NIP_TCP #      1 --:1024
Sending  -- 1661760203  69254 NIP_TCP #      1 --:1024
Received -- 1661760203 571604 NIP_TCP #      2 --:1024
Sending  -- 1661760203 571604 NIP_TCP #      2 --:1024
...
Received -- 1661760207  86544 NIP_TCP #      9 --:1024
Sending  -- 1661760207  86544 NIP_TCP #      9 --:1024

客户端shell窗口打印内容:
Received --1661760202 560605 NIP_TCP #      0 sock 3 success:     1/     1/no=     0
Received --1661760203  69254 NIP_TCP #      1 sock 3 success:     2/     2/no=     1
...
Received --1661760207  86544 NIP_TCP #      9 sock 3 success:    10/    10/no=     9

selinux规则说明

用户态进程操作New IP socket需要添加selinux policy,否则操作会被拦截。

# base\security\selinux\sepolicy\ohos_policy\xxx\xxx.te
# socket 基础操作
# avc:  denied  { create } for  pid=540 comm="thread_xxx" scontext=u:r:thread_xxx:s0 tcontext=u:r:thread_xxx:s0 tclass=socket permissive=0
allow thread_xxx thread_xxx:socket { create bind connect listen accept read write shutdown setopt getopt };

# ioctl 操作
# 操作码在 linux-xxx\include\uapi\linux\sockios.h 中定义
# 0x8933 : name -> if_index mapping
# 0x8916 : set PA address
# 0x890B : add routing table entry
allowxperm thread_xxx thread_xxx:socket ioctl { 0x8933 0x8916 0x890B };
    sh

WireShark报文解析模板

Wireshark默认报文解析规则无法解析New IP报文,在WireShark配置中添加New IP报文解析模板可以实现New IP报文解析,​​New IP报文解析模板​​详见代码仓。

报文解析模板配置文件的方法:

依次单击 Help -> About Wireshark -> Folders,打开Global Configuration目录,编辑init.lua文件。在末尾添加dofile(DATA_DIR…”newip.lua”),其中DATA_DIR即为newip.lua报文解析模板所在路径。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

New IP报文解析模板添加样例:

New IP报文解析模板存放路径:
D:\tools\WireShark\wireshark_cfg_for_newip.lua

WireShark配置文件路径:
C:\Program Files\Wireshark\init.lua

在init.lua文件最后增加下面配置(window 11)
dofile("D:\\tools\\WireShark\\wireshark_cfg_for_newip.lua")
报文解析样例
ND请求

New IP邻居发现(Neighbor Discovery)请求报文格式如下,New IP极简报文头包含1字节的bitmap(0x76),bitmap标识后面携带TTL,报文总长度,上层协议类型,目的地址,源地址。New IP ND请求报文包含报文类型,操作码,校验和和请求地址。

备注:New IP支持变长地址(1字节~8字节),下图中1字节地址仅表示当前报文头中携带的地址是1字节。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

ND应答

New IP邻居发现(Neighbor Discovery)应答报文格式如下,New IP极简报文头包含2字节的bitmap(0x77,0x00),bitmap1标识后面携带TTL,报文总长度,上层协议类型,目的地址,源地址。bitmap2是字节对齐不携带任何数据(rk3568开发板链路层数据发送要求数据长度是偶数字节)。New IP ND应答报文包含报文类型,操作码,校验和和邻居MAC地址长度,邻居MAC地址。

备注:New IP支持变长地址(1字节~8字节),下图中1字节地址仅表示当前报文头中携带的地址是1字节。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

TCP握手

TCP三次握手SYN报文格式如下,New IP极简报文头包含2字节的bitmap(0x77,0x00),bitmap1标识后面携带TTL,报文总长度,上层协议类型,目的地址,源地址。bitmap2是字节对齐不携带任何数据(rk3568开发板链路层数据发送要求数据长度是偶数字节)。

备注:New IP支持变长地址(1字节~8字节),下图中1字节地址仅表示当前报文头中携带的地址是1字节。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

TCP数据包

TCP数据格式如下,New IP极简报文头包含2字节的bitmap(0x77,0x00),bitmap1标识后面携带TTL,报文总长度,上层协议类型,目的地址,源地址。bitmap2是字节对齐不携带任何数据(rk3568开发板链路层数据发送要求数据长度是偶数字节)。

备注:New IP支持变长地址(1字节~8字节),下图中1字节地址仅表示当前报文头中携带的地址是1字节。

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区

OpenHarmony设备开发标准系统内核(Linux) 内核增强特性-鸿蒙开发者社区


文章转载自:​​https://docs.openharmony.cn/pages/v3.2Beta/zh-cn/device-dev/kernel/kernel-standard-newip.md/​

分类
已于2023-4-14 16:15:45修改
收藏
回复
举报
回复
    相关推荐