用户空间协议栈设计和netmap综合指南

本文分享自华为云社区《用户空间协议栈设计和netmap综合指南,将网络效率提升到新高度》,作者:Lion Long 。

协议概念

1.1、七层网络模型和五层网络模型

cke_140.png

cke_141.png

应用层: 最接近用户的一层,为用户程序提供网络服务。主要协议有HTTP、FTP、TFTP、SMTP、DNS、POP3、DHCP等。

表示层: 数据的表示、安全、压缩。管理数据的解密和加密。

会话层: 负责在网络中的两个节点之间的建立、维持和终止通信。

传输层: 模型中最重要的一层,负责传输协议的流控和差错校验。数据包离开网卡后进入的就是传输层;主要协议有:TCP、UDP等。

网络层: 将网络地址翻译成对应的物理地址。主要协议有:ICMP、IP等。

数据链路层: 建立逻辑连接、进行硬件地址寻址、差错校验等功能,解决两台相连主机之间的通信问题。主要协议有SLIP、以太网协议/MAC帧协议、ARP和RARP等。

物理层: 模型的最低层,建立、维护、断开物理连接,传输比特流。常见的物理媒介有光纤、电缆、中继器等。主要协议有RS232等。

1.2、以太网

以太网不是一种网络,而是一种局域网技术,它既有数据链路层内容,也有一些物理层内容。局域网技术除了以太网外,还有令牌环网、无线LAN/WAN等。

以太网的网线必须是双绞线,以太网中的所有主机共享一个通信通道; 当局域网中一台主机发送数据后,该局域网的所有设备都会收到该数据。因为共用一个通信通道,因此同一时刻只允许一台主机发送数据;如果同一时刻不只有一个主机发送数据,为避免干扰,该主机会执行碰撞避免算法(等待一段时间后再进行数据重发)。

以太网帧格式如下:

cke_142.png

源地址和目的地址是指网卡MAC地址,长度是48 bit(6字节)。帧协议类型字段有三种,分别对应IP协议、ARP协议和RARP协议。帧末尾是CRC校验码。

定义一个以太网头结构体示例代码:

#define ETHER_ADDR_LEN 6

struct etherhdr {

unsigned char dst_mac[ETHER_ADDR_LEN];

unsigned char src_mac[ETHER_ADDR_LEN];

unsigned short protocol;

};复制

输出它的大小:

sizeof(struct etherhdr) = 14复制

1.3、IP协议

IP协议全称Internet Protocol,即网际互连协议,存在于网络层,负责数据在网络中传输。

IP协议格式如下:

0 |1 |2 |3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-------+-------+---------------+-------------------------------+

|version|hdr_len| Type Of Server| total length |

+-------------------------------+-----+-------------------------+

| ID |flag | framegament offset |

+---------------+---------------+-------------------------------+

| TTL | Protocol | header CRC |

+---------------------------------------------------------------+

| Source IP |

+---------------------------------------------------------------+

| Destination IP |

+---------------------------------------------------------------+

| Option (if have) |

+---------------------------------------------------------------+

| Data |

| ... |

+---------------------------------------------------------------+复制

定义一个IP协议头结构体示例代码:

struct iphdr {

unsigned char version : 4,

hdrlen : 4;



unsigned char tos;

unsigned short totlen;

unsigned short id;

unsigned short flag : 3,

offset : 13;

unsigned char ttl;

unsigned char protocol;

unsigned short check;

unsigned int sip;

unsigned int dip;

};复制

1.4、ARP协议

ARP协议全称Address Resolution Protocol,即地址解析协议,是根据IP地址获取MAC地址的一个TCP/IP协议。

ARP协议的作用:在同一个局域网中要给对方发消息,就必须得知道对方的MAC地址,而实际大部分情况下只知道对方的IP地址,因此需要通过ARP协议来根据IP地址来获取目标主机的MAC地址。

ARP的数据格式如下:

0 |1 |2 |3 |4 |5

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7

+-----------------------------------------------------------------------------------------------+

| Ethernet Destination IP |

+-----------------------------------------------------------------------------------------------+

| Ethernet Source IP |

+-------------------------------+-------------------------------+-------------------------------+

| framegament type | harware address tpye | Protocol address type |

+---------------+---------------+-------------------------------+-------------------------------+

| HW_addr_length|Pro_addr_len | op code | Source MAC |

+---------------------------------------------------------------+-------------------------------|

| Source MAC | Source IP |

+-------------------------------+---------------------------------------------------------------|

| Source IP | Destination MAC |

+-------------------------------+---------------------------------------------------------------+

| Destination MAC | Destination IP |

+-----------------------------------------------------------------------------------------------+

| |

| PAD |

| |

+-----------------------------------------------------------------------------------------------+复制

可以看出,ARP是MAC帧协议的上层协议,前3个字段和最后一个字段对应的就是以太网头部。由于ARP数据包的长度不足46字节,因此ARP数据包在封装成为MAC帧时还需要补上18字节的填充字段。

定义一个arp协议头结构体示例代码:

struct arphdr{

unsigned short h_type;

unsigned short h_proto;

unsigned char h_addrlen;

unsigned char protolen;

unsigned short oper;

unsigned char smac[ETH_ALEN];

unsigned int sip;

unsigned char dmac[ETH_ALEN];

unsigned int dip;

// pad

};复制

1.4.1、ARP攻击原理

arp攻击得到主要目的是使网络无法正常通信。 向局域网中的所有主机发送ARP应答,其中包含网关IP地址和虚假的MAC地址。局域网中的主机收到ARP应答跟新ARP表后,再发送数据时,就会发送到虚假的MAC地址导致通信故障,就无法和网关正常通信,导致无法访问互联网。

1.4.2、ARP欺骗原理

ARP欺骗并不会使网络无法正常通信,而是通过冒充网关或其他主机 使得 到达网关或主机的数据流量通过攻击主机进行转发。

比如冒充网关:ARP欺骗发送arp应答给局域网中其他的主机,其中包含网关的IP地址和进行ARP欺骗的主机MAC地址;并且也发送了ARP应答给网关,其中包含局域网中所有主机的IP地址和进行arp欺骗的主机MAC地址。当局域网中主机和网关收到ARP应答跟新ARP表后,主机和网关之间的流量就需要通过攻击主机进行转发。

冒充主机的过程和冒充网关相同。

1.5、ICMP协议

ICMP全称Internet Control Message Protocol,即互联网控制消息协议,位于 IP 报文的数据段。虽然ICMP是网络层协议,但它不直接传递数据到数据链路层,而是封装成IP数据包再传递到数据链路层,IP数据包中的协议类型字段为1就表示ICMP报文。ICMP协议的类型主要有两类:查询报文和差错报文。

ICMP报文格式如下:

0 |1 |2 |3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+---------------+---------------+-------------------------------+

| type | code | CRC |

+-------------------------------+-------------------------------+

| ID | Sequence Number |

+---------------------------------------------------------------+

| mask |

+---------------------------------------------------------------+复制

标识

含义

type

类型,0 代表应答 ICMP 报文、8 代表请求 ICMP 报文。

code

代码,type= 8 && code= 0 表示回显请求(ping 请求);type= 0 && code= 0 表示回显应答(ping 应答);type = 11 && code = 0 表示超时。

CRC

校验和,包括数据在内的整个 ICMP 数据报的检验和

ID

标识符,将发送进程的 ID 号放置在标识符字段,这样即使在主机上运行了多个 ping 程序,ping 程序也可以识别出返回的信息。

Sequence Number

序列号,从 0 开始,每发送一次心得回显请求就加 1 。

mask

子网掩码

定义一个ICMP协议头结构体示例代码:

// ICMP

struct icmphdr {

unsigned char type;

unsigned char code;

unsigned short check;

unsigned short identifier;

unsigned short sep;

unsigned cahr data[32];

};复制

ICMP的应用:

(1)ping命令。向目的服务器发送回显请求,目的服务器发送回显应答;计算发送回显请求数据包的时间与接收到回显应答数据包的时间差,就是数据包一去一回所需要的时间。

(2)traceroute命令。traceroute命令利用 ICMP 差错报文类型,用作追踪路由信息。前提条件是路由器没有禁用 ICMP。

1.6、MTU概念

MTU,全称Maximum Transmission Unit,即最大传输单元。说明一次数据帧可以发送或接收的最大数据量;以字节为单位,一般是是1500,不同网络类型的MTU不同。

(1)如果一次发送要发送的数据超过MTU,需要在IP层对数据进行分片。数据分片和组装在IP层,因为不同网络的MTU不同,不仅源主机可能需要对数据进行分片,数据传输过程中的路由器也可能对数据分片。

(2)以太网规定数据的最小长度为46字节,如果发送数据小于46字节,需要填充,比如ARP数据包就需要填充才能发送。

(3)对于UDP,是定长的8字节报头,如果IP报头没有携带可选项字段,那么UDP一次携带的数据最大为1500-20-8=1472字节,如果超出这个大小就需要在IP层进行分片。分片带来的后果是增加UDP的丢包率。

(4)分片也会增加TCP的丢包率,不过TCP有重传机制;因此需要尽可能避免分片,降低TCP重传次数。

1.7、MSS概念

MSS,全称Maximum Segment Size,即最大报文段大小。表示TCP传往另一端的最大块数据的长度。

当一个连接建立时,连接的双方都要提供各自的MSS。通过协商确定MSS的值(双方MSS的最小值)以避免TCP分片。如果没有分段发生, MSS越大越好。

1.8、TTL概念

TTL,全称Time To Live,即存活时间;指一个数据包可传递的最长距离(跃点数)。

当一个数据包经过一个路由器时,TTL减一;当TTL=0时路由器就会取消数据包的转发。

我们知道网络是有 环 存在的,设计TTL的目的是防止数据包因为不正确的路由表等原因造成无线循环而无法送达导致耗尽网络资源。

二、数据传输框图

网络上所有的数据传输都要经过网卡,网卡将模拟信号转换为数字信号,也就是将物理层信号转换为数据链路层信号。

cke_143.png

注意:

(1)send()返回成功不代表发送成功,send()只是包数据拷贝到写缓冲区,真正发送数据由协议栈完成。如果客户端宕机而服务端一直执行send(),那么在一段时间后send()会返回-1;因为写缓冲区中的数据没有发送出去导致写缓冲区爆满。

(2)协议栈就是数据根据七层网络模型,自顶向下一层一层的协议头包住数据;接收端也是根据七层网络模型,自底向上一层层的解析协议。

(3)驱动如何把数据传递到协议栈?

在Linux kernel有一个sk_buffer结构,sk_buffer将驱动获取的数据通过sk_buffer传递到协议栈中。

三、校验和 checksum的计算方法

(1) 先将需要计算checksum数据中的checksum字段设为0;

(2) 将checksum的数据按2 byte(16 bit)划分,如果最后有单个byte的数据,则在其后面补1 byte的0构成2 byte;

(3) 将所有的2 byte(16 bit)z值累加,得到一个4 byte(32 bit)的值;

(4)将得到的4 byte(32 bit)的值的高16bit与低16bit相加得到一个新的4 byte(32 bit)值;若新值大于0xFFFF,再将新值的高16bit与低16bit相加。

(5)将上一步计算所得的值按位取反,即得到checksum值,保存到checksum字段即可。

示例代码:

unsigned short in_cksum(unsigned short *addr,int len)

{

register int nleft = len;

register unsigned short *w = addr;

register int sum = 0;//32bit

unsigned short answer = 0;//16bit

while (nleft > 1)

{

sum += *w++;//16bit为一组累加

nleft -= 2;

}

if (nleft == 1)//存在单个byte情况

{

*(u_char*)(&answer) = *(u_char*)w;

sum += answer;

}

sum = (sum >> 16) + (sum & 0xffff);// 高16bit与低16bit相加

sum += (sum >> 16);//防止值大于0xffff

//结果

answer = ~sum;

return (answer);

}复制

四、协议栈设计–netmap

要实现一个协议栈,那么就需要获得原始的协议数据。

cke_144.png

4.1、获取原始协议数据的方法

(1)raw socket,即原始套接字,可以接收本机网卡的数据帧或数据包。有四种方式创建这类socket。

目标

实现

发送接收IP数据包

socket(PF_INET,SOCK_RAW,IPPROTO_TCP | IPPROTO_UDP | IPPROTO_ICMP) ;

发送接收以太网数据帧

socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP | ETH_P_ARP | ETH_P_ALL));

发送接收以太网数据帧(不包括以太网头部)

socket(PF_PACKET,SOCK_DGRAM,htons(ETH_P_IP | ETH_P_ARP | ETH_P_ALL));

(2)旁路。netmap、dpdk等

(3)hook。bpf、ebpf等

4.2、零长数组

零长数组,顾名思义,就是长度为零的数组。一般在GUN C中使用,其他编译器使用可能会报错或警告。

零长度数组的一个特点是它不占用内存存储空间。如下示例:

#include <stdio.h>

char test[0];

int main()

{

printf("size = %ld\n",sizeof(test));

return 0;

}

// 输出 为 0复制

在结构体中使用,它同样也不占内存:

#include <stdio.h>

struct test{

int len;

int ch[0];

};

int main(void)

{

printf("size of = %ld\n",sizeof(struct test));

return 0;

}复制

零长数组的使用:内存已经分配,但数据长度不确定,需要计算出数据长度的,就可以使用零长数组。零长数组在内存池中使用比较多。

使用示例:

#include <stdio.h>

struct test{

int len;

char ch[0];

};

int main(void)

{

struct test *buf;

buf = (struct test *)malloc(sizeof(struct test)+ 16);

memset(buf,0,sizeof(struct test)+ 16);



strcpy(buf->ch, "hello world\n");

puts(buf->ch);



free(buf);

return 0;

}复制

4.3、修改ens33为eth0

(1)打开/etc/default/grub

sudo nano /etc/default/grub复制

(2)找到GRUB_CMDLINE_LINUX=" "改为GRUB_CMDLINE_LINUX=“net.ifnames=0 biosdevname=0”

(3)写入配置

sudo grub-mkconfig -o /boot/grub/grub.cfg复制

(4)重启系统

reboot复制

4.4、netmap下载安装

以ubuntu为例。

(1)切换到根目录:

cd /复制

(2)切换到root权限:

sudo su复制

(3)在根目录clone netmap:

git clone https://github.com/luigirizzo/netmap.git复制

正克隆到 'netmap'...

remote: Enumerating objects: 28670, done.

remote: Counting objects: 100% (978/978), done.

remote: Compressing objects: 100% (397/397), done.

remote: Total 28670 (delta 603), reused 867 (delta 533), pack-reused 27692复制

接收对象中: 100% (28670/28670), 10.13 MiB | 2.72 MiB/s, 完成.

处理 delta 中: 100% (18306/18306), 完成.

(4)安装编译环境:

apt-get install build-essential复制

(5)进入netmap/LINUX 目录:

cd /netmap/LINUX/复制

(6)执行配置:

./configure复制

此过程会下载一些东西,然后提示耐心等待一段时间,过程有点久,请耐心等待,如下。

cke_145.png

(7)编译和安装:

make && make install复制

此过程也需要耐心等待一段时间,过程有点久。

......

##install -D -m 644 ice.7.gz //usr/share/man/man7/ice.7.gz

/sbin/depmod -e -F /boot/System.map-4.15.0-142-generic -a 4.15.0-142-generic

Updating initramfs...

update-initramfs -u

update-initramfs: Generating /boot/initrd.img-4.15.0-142-generic

make[1]: Leaving directory '/netmap/LINUX/ice-1.7.16/src'

make -C ixgbe install INSTALL_MOD_PATH= CFLAGS_EXTRA="-Wno-unused-but-set-variable -Wno-attributes -Wno-maybe-uninitialized -Wno-unused-variable -Wno-unused-label -I/netmap/LINUX -I/netmap/LINUX -I/netmap/LINUX/../sys -I/netmap/LINUX/../sys/dev -DCONFIG_NETMAP -Wno-unused-but-set-variable -g -DCONFIG_NETMAP_NULL -DCONFIG_NETMAP_PTNETMAP -DCONFIG_NETMAP_GENERIC -DCONFIG_NETMAP_MONITOR -DCONFIG_NETMAP_PIPE -DCONFIG_NETMAP_VALE" NETMAP_DRIVER_SUFFIX= KSRC=/lib/modules/4.15.0-142-generic/build KBUILD_EXTRA_SYMBOLS=/netmap/LINUX/Module.symvers

make[1]: Entering directory '/netmap/LINUX/ixgbe-5.3.8/src'

make[2]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

Building modules, stage 2.

MODPOST 1 modules

make[2]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

Copying manpages...

Installing modules...

make[2]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

INSTALL /netmap/LINUX/ixgbe-5.3.8/src/ixgbe.ko

At main.c:160:

- SSL error:02001002:system library:fopen:No such file or directory: bss_file.c:175

- SSL error:2006D080:BIO routines:BIO_new_file:no such file: bss_file.c:178

sign-file: certs/signing_key.pem: No such file or directory

DEPMOD 4.15.0-142-generic

make[2]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

Running depmod...

make[1]: Leaving directory '/netmap/LINUX/ixgbe-5.3.8/src'

make -C igb install INSTALL_MOD_PATH= CFLAGS_EXTRA="-DDISABLE_PACKET_SPLIT -fno-pie -I/netmap/LINUX -I/netmap/LINUX -I/netmap/LINUX/../sys -I/netmap/LINUX/../sys/dev -DCONFIG_NETMAP -Wno-unused-but-set-variable -g -DCONFIG_NETMAP_NULL -DCONFIG_NETMAP_PTNETMAP -DCONFIG_NETMAP_GENERIC -DCONFIG_NETMAP_MONITOR -DCONFIG_NETMAP_PIPE -DCONFIG_NETMAP_VALE" NETMAP_DRIVER_SUFFIX= KSRC=/lib/modules/4.15.0-142-generic/build KBUILD_EXTRA_SYMBOLS=/netmap/LINUX/Module.symvers

make[1]: Entering directory '/netmap/LINUX/igb-5.3.5.20/src'

make[2]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

Building modules, stage 2.

MODPOST 1 modules

make[2]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

Copying manpages...

Installing modules...

make[2]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

INSTALL /netmap/LINUX/igb-5.3.5.20/src/igb.ko

At main.c:160:

- SSL error:02001002:system library:fopen:No such file or directory: bss_file.c:175

- SSL error:2006D080:BIO routines:BIO_new_file:no such file: bss_file.c:178

sign-file: certs/signing_key.pem: No such file or directory

DEPMOD 4.15.0-142-generic

make[2]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

Running depmod...

make[1]: Leaving directory '/netmap/LINUX/igb-5.3.5.20/src'

make -C virtio_net.c install INSTALL_MOD_PATH= EXTRA_CFLAGS="-I/netmap/LINUX -I/netmap/LINUX -I/netmap/LINUX/../sys -I/netmap/LINUX/../sys/dev -DCONFIG_NETMAP -Wno-unused-but-set-variable -g -DCONFIG_NETMAP_NULL -DCONFIG_NETMAP_PTNETMAP -DCONFIG_NETMAP_GENERIC -DCONFIG_NETMAP_MONITOR -DCONFIG_NETMAP_PIPE -DCONFIG_NETMAP_VALE" NETMAP_DRIVER_SUFFIX= KSRC=/lib/modules/4.15.0-142-generic/build

make[1]: Entering directory '/netmap/LINUX/virtio_net.c'

make -C "/lib/modules/4.15.0-142-generic/build" M=/netmap/LINUX/virtio_net.c modules_install

make[2]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

INSTALL /netmap/LINUX/virtio_net.c/virtio_net.ko

At main.c:160:

- SSL error:02001002:system library:fopen:No such file or directory: bss_file.c:175

- SSL error:2006D080:BIO routines:BIO_new_file:no such file: bss_file.c:178

sign-file: certs/signing_key.pem: No such file or directory

DEPMOD 4.15.0-142-generic

make[2]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

make[1]: Leaving directory '/netmap/LINUX/virtio_net.c'

make -C build-apps/dedup install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/dedup'

install -D dedup //usr/local/bin/dedup

install -D -m 644 /netmap/LINUX/../apps/lb/lb.8 //usr/local/share/man/man8/lb.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/dedup'

make -C build-apps/vale-ctl install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/vale-ctl'

install -D vale-ctl //usr/local/bin/vale-ctl

install -D -m 644 /netmap/LINUX/../apps/vale-ctl/vale-ctl.4 //usr/local/share/man/man4/vale-ctl.4

make[1]: Leaving directory '/netmap/LINUX/build-apps/vale-ctl'

make -C build-apps/nmreplay install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/nmreplay'

install -D nmreplay //usr/local/bin/nmreplay

install -D -m 644 /netmap/LINUX/../apps/nmreplay/nmreplay.8 //usr/local/share/man/man8/nmreplay.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/nmreplay'

make -C build-apps/tlem install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/tlem'

install -D tlem //usr/local/bin/tlem

install -D -m 644 /netmap/LINUX/../apps/tlem/tlem.8 //usr/local/share/man/man8/tlem.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/tlem'

make -C build-apps/lb install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/lb'

install -D lb //usr/local/bin/lb

install -D -m 644 /netmap/LINUX/../apps/lb/lb.8 //usr/local/share/man/man8/lb.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/lb'

make -C build-apps/bridge install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/bridge'

install -D bridge //usr/local/bin/bridge

install -D -m 644 /netmap/LINUX/../apps/bridge/bridge.8 //usr/local/share/man/man8/bridge.8

install -D bridge-b //usr/local/bin/bridge-b

install -D -m 644 /netmap/LINUX/../apps/bridge/bridge.8 //usr/local/share/man/man8/bridge.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/bridge'

make -C build-apps/pkt-gen install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-apps/pkt-gen'

install -D pkt-gen //usr/local/bin/pkt-gen

install -D -m 644 /netmap/LINUX/../apps/pkt-gen/pkt-gen.8 //usr/local/share/man/man8/pkt-gen.8

install -D pkt-gen-b //usr/local/bin/pkt-gen-b

install -D -m 644 /netmap/LINUX/../apps/pkt-gen/pkt-gen.8 //usr/local/share/man/man8/pkt-gen.8

make[1]: Leaving directory '/netmap/LINUX/build-apps/pkt-gen'

install -m 0644 -D /netmap/LINUX/../sys/net/netmap.h //usr/local/include/net/netmap.h

install -m 0644 -D /netmap/LINUX/../sys/net/netmap_user.h //usr/local/include/net/netmap_user.h

install -m 0644 -D /netmap/LINUX/../sys/net/netmap_virt.h //usr/local/include/net/netmap_virt.h

install -m 0644 -D /netmap/LINUX/../sys/net/netmap_legacy.h //usr/local/include/net/netmap_legacy.h

install -m 0644 -D /netmap/LINUX/../libnetmap/libnetmap.h //usr/local/include/libnetmap.h

install -D -m 644 /netmap/LINUX/../share/man/man4/netmap.4 //usr/local/share/man/man4/netmap.4

install -D -m 644 /netmap/LINUX/../share/man/man4/vale.4 //usr/local/share/man/man4/vale.4

install -D -m 644 /netmap/LINUX/../share/man/man4/ptnet.4 //usr/local/share/man/man4/ptnet.4

make -C build-libnetmap install SRCDIR=/netmap/LINUX/.. BUILDDIR=/netmap/LINUX DESTDIR="" PREFIX="/usr/local"

make[1]: Entering directory '/netmap/LINUX/build-libnetmap'

install -D libnetmap.a //usr/local/lib/libnetmap.a

make[1]: Leaving directory '/netmap/LINUX/build-libnetmap'复制

(8)使用netmap:

insmod netmap.ko复制

每次使用前都要执行insmod netmap.ko,它在/netmap/LINUX/路径下。

(9)检查netmap是否insmod成功:

ls /dev/netmap -l复制

出现如下表示成功:

crw------- 1 root root 10, 54 8月 31 12:53 /dev/netmap复制

(10)编译运行自己的代码

# 头文件 #include<net/netmap_user.h> 在 /netmap/sys/目录下

# 和/usr/local/include/net/目录下

gcc -o testcode testcode.c -I /netmap/sys/复制

4.5、协议栈实现代码示例

示例简单实现了arp、icmp、udp的协议栈;其他协议的实现类似。

//需要开启netmap的宏

#define NETMAP_WITH_LIBS

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

#include <net/netmap_user.h>

#include <sys/poll.h>

#include <arpa/inet.h>

#pragma pack(1)//设置一字节对齐方式

#define ETH_ALEN 6

#define PROTO_IP 0x0800 // IP 协议

#define PROTO_ARP 0x0806

#define PROTOCOL_UDP 17

#define PROTO_ICMP 1

#define PROTO_IGMP 2

#define ICMP_TYPE_ANS 0

#define ICMP_TYPE_REQ 8

#define ETHER_ADDR_LEN 6

#define MY_IP "192.168.7.146"

#define MY_MAC "00:0c:29:39:a8:c4"

// ether

struct etherhdr {

unsigned char dst_mac[ETHER_ADDR_LEN];

unsigned char src_mac[ETHER_ADDR_LEN];

unsigned short protocol;

};

// IP

struct iphdr {

unsigned char version : 4,

hdrlen : 4;



unsigned char tos;

unsigned short totlen;

unsigned short id;

unsigned short flag : 3,

offset : 13;

unsigned char ttl;

unsigned char protocol;

unsigned short check;

unsigned int sip;

unsigned int dip;

};

// UDP

struct udphdr {

unsigned short sport;

unsigned short dport;

unsigned short length;

unsigned short check;

};

struct udppkt {

struct etherhdr eth;

struct iphdr ip;

struct udphdr udp;

unsigned char payload[0];// 零长数组

};

// ARP

struct arphdr{

unsigned short h_type;

unsigned short h_proto;

unsigned char h_addrlen;

unsigned char protolen;

unsigned short oper;

unsigned char smac[ETH_ALEN];

unsigned int sip;

unsigned char dmac[ETH_ALEN];

unsigned int dip;

};

struct arppkt {

struct etherhdr eth;

struct arphdr arp;

};

// ICMP

struct icmphdr {

unsigned char type;

unsigned char code;

unsigned short check;

unsigned short identifier;

unsigned short sep;

unsigned char data[32];

};

struct icmppkt{

struct etherhdr eth;

struct iphdr ip;

struct icmphdr icmp;

};

void echo_udp_pkt(struct udppkt *udp,struct udppkt *udp_rt)

{

memcpy(udp_rt, udp, sizeof(struct udppkt));

memcpy(udp_rt->eth.dst_mac, udp->eth.src_mac, ETH_ALEN);

memcpy(udp_rt->eth.src_mac, udp->eth.dst_mac, ETH_ALEN);

udp_rt->ip.sip = udp->ip.dip;

udp_rt->ip.dip = udp->ip.sip;

udp_rt->udp.sport = udp->udp.dport;

udp_rt->udp.dport = udp->udp.sport;

}

unsigned short in_cksum(unsigned short *addr,int len)

{

register int nleft = len;

register unsigned short *w = addr;

register int sum = 0;//32bit

unsigned short answer = 0;//16bit

while (nleft > 1)

{

sum += *w++;//16bit为一组累加

nleft -= 2;

}

if (nleft == 1)//存在单个byte情况

{

*(u_char*)(&answer) = *(u_char*)w;

sum += answer;

}

sum = (sum >> 16) + (sum & 0xffff);// 高16bit与低16bit相加

sum += (sum >> 16);//防止值大于0xffff

//结果

answer = ~sum;

return (answer);

}

void echo_icmp_pkt(struct icmppkt *icmp, struct icmppkt *icmp_rt)

{

memcpy(icmp_rt, icmp, sizeof(struct icmppkt));

memcpy(icmp_rt->eth.dst_mac, icmp->eth.src_mac, ETH_ALEN);

memcpy(icmp_rt->eth.src_mac, icmp->eth.dst_mac, ETH_ALEN);

icmp_rt->icmp.type = ICMP_TYPE_ANS;

icmp_rt->icmp.code = 0;

icmp_rt->icmp.check = 0;

icmp_rt->ip.sip = icmp->ip.dip;

icmp_rt->ip.dip = icmp->ip.sip;

icmp_rt->icmp.check = in_cksum((unsigned short*)&icmp_rt->icmp, sizeof(struct icmphdr));

}

int str2mac(char *mac, char *str) {

char *p = str;

unsigned char value = 0x0;

int i = 0;

while (p != '\0') {

if (*p == ':') {

mac[i++] = value;

value = 0x0;

}

else {

unsigned char temp = *p;

if (temp <= '9' && temp >= '0') {

temp -= '0';

}

else if (temp <= 'f' && temp >= 'a') {

temp -= 'a';

temp += 10;

}

else if (temp <= 'F' && temp >= 'A') {

temp -= 'A';

temp += 10;

}

else {

break;

}

value <<= 4;

value |= temp;

}

p++;

}

mac[i] = value;

return 0;

}

void echo_arp_pkt(struct arppkt *arp, struct arppkt *arp_rt, char *hmac) {

memcpy(arp_rt, arp, sizeof(struct arppkt));

memcpy(arp_rt->eth.dst_mac, arp->eth.src_mac, ETH_ALEN);

str2mac(arp_rt->eth.src_mac, hmac);

arp_rt->eth.protocol = arp->eth.protocol;

arp_rt->arp.h_addrlen = 6;

arp_rt->arp.protolen = 4;

arp_rt->arp.oper = htons(2);

str2mac(arp_rt->arp.smac, hmac);

arp_rt->arp.sip = arp->arp.dip;

memcpy(arp_rt->arp.dmac, arp->arp.smac, ETH_ALEN);

arp_rt->arp.dip = arp->arp.sip;

}

// netmap

int main()

{

printf("length = %ld\n", sizeof(struct etherhdr));

struct pollfd pfd = { 0 };// poll

struct nm_pkthdr h;

struct etherhdr *eh;

// 打开/dev/netmap,映射网卡数据到内存空间

struct nm_desc *nmr = nm_open("netmap:eth0", NULL,0,NULL);

if (nmr == NULL)

{

printf("netmap open fail!\n");

return -1;

}

pfd.fd = nmr->fd;// 指向/dev/netmap

pfd.events = POLLIN;//监听读事件

while (1)

{

int ret = poll(&pfd, 1, -1);

if (ret < 0)

continue;

if (pfd.events & POLLIN)//操作内存

{

unsigned char *stream = nm_nextpkt(nmr, &h);//从环形队列中取出一个数据包

eh = (struct etherhdr *)stream;

//将网络数据转换为本地字节序

if (ntohs(eh->protocol) == PROTO_IP)

{

struct udppkt *pkt = (struct udppkt *)stream;

if (pkt->ip.protocol == PROTOCOL_UDP)

{

struct in_addr addr;

addr.s_addr = pkt->ip.sip;

// udp包length字段表示的是整个UDP包的总长度(包含udp的头长度)

int length = ntohs(pkt->udp.length);

printf("%s:%d:length:%d,ip length:%d\n",

inet_ntoa(addr),

pkt->udp.sport,

length,

ntohs(pkt->ip.totlen));

pkt->payload[length - 8] = '\0';

printf("pkt: %s\n", pkt->payload);

struct udppkt udp_rt;

echo_udp_pkt(pkt, &udp_rt);

nm_inject(nmr, &udp_rt, sizeof(struct udppkt));

}

else if (pkt->ip.protocol == PROTO_ICMP)

{

struct icmppkt *icmp = (struct icmppkt*)stream;

printf("icmp------> %d,%x\n",

icmp->icmp.type,icmp->icmp.check);

if (icmp->icmp.type == ICMP_TYPE_REQ)//0 代表应答 ICMP 报文、8 代表请求 ICMP 报文。

{

struct icmppkt icmp_rt = { 0 };

echo_icmp_pkt(icmp, &icmp_rt);

nm_inject(nmr, &icmp_rt, sizeof(struct icmppkt));

}

}

else if (pkt->ip.protocol == PROTO_IGMP)

{

printf("PROTO_IGMP packet\n");

}

else

{

printf("other ip packet\n");

}

}

else if (ntohs(eh->protocol) == PROTO_ARP)

{

struct arppkt *arp = (struct arppkt*)stream;

struct arppkt arp_rt;

if (arp->arp.dip == inet_addr(MY_IP))

{

echo_arp_pkt(arp, &arp_rt, MY_MAC);

nm_inject(nmr, &arp_rt, sizeof(struct arppkt));

}

}

}

}

return 0;

}复制

总结

要实现一个协议栈,需要清楚七层网络模型,熟悉协议标准;获得协议的原始数据包后需要一层层的拨开解析;发送数据之前需要将协议一层层的往下包装。

cke_146.png

点击关注,第一时间了解华为云新鲜技术~

暂无评论

相关推荐

鸿蒙案例上新啦 | 出门打车、到家上课:25个模板带你一屏打通日常生活

如何合理拆分页面组件、如何建立单一可信的状态源、如何让用户在每一步操作中都获得明确反馈。鸿蒙开发实践中心以标准化的应用与元服务模板为入口,将清晰的业务架构与可复用的代码结构直观呈现。不妨立即挑选一个感兴趣的方向进入云端环境,从页面布局、组件封装、状态管理到路由组织,亲手跑通你的鸿蒙实战项目。

华为云官方博客 17

LakeAgent:DWS数据仓库的第二大脑,告别 “翻译式运维”,迈入智能自治时代

和普通 SQL 改写工具不同,LakeAgent 自动做多方案代价对比,主动规避负优化陷阱:补充分区键过滤实现剪枝,扫描分区由 37 收敛至 1,执行代价从 758.28 降至 113.74;未来的数据仓库,将不止能算、能存,更能看懂自己、诊断自己、理解自己。长久以来,数仓的智能都依附于人:信号需要人解读,瓶颈需要人研判,经验困在个体里,无法随底座永续生长。CPU 高、CPU 告警、CPU 诊断、CPU 使用率过高、CPU 满。语法、错误码、计费、性能调优、最佳实践、故障处置等全场景内容。

华为云官方博客 496

如何使用RDS Supabase后端BaaS能力:文件存储(File Storage)

• product-images(公开桶,允许公共读取):策略名称"Public read for product-images",允许SELECT,目标角色anon,策略定义bucket_id = 'product-images'。上传/删除需另配INSERT/DELETE策略,详见SQL。• product-specs(私有桶,仅认证用户访问自己的文件夹):建议拆为上传、读取、删除三条策略,策略定义均为 bucket_id = 'product-specs' 且仅限本人文件夹(详见下文 SQL)。

华为云官方博客 429

如何使用RDS Supabase后端BaaS能力:实时订阅与推送(Realtime)

Realtime 把数据库的每次变更同步到客户端:表里增、删、改一行,订阅者无需刷新页面或主动请求即可秒级收到。三大能力各司其职:• Postgres Changes — 监听表的 INSERT/UPDATE/DELETE,变化即通知• Broadcast — 客户端之间直接互发,适合瞬时通知、协同编辑• Presence — 跟踪频道里“谁在线”典型场景有实时数据展示(订单、库存、监控指标即时刷新)、即时通讯(消息收发、在线名单、“对方正在输入”)、协同编辑与实时通知。

华为云官方博客 418

AI Agent如何通过MCP连接到华为云RDS Supabase应用平台

Schema元数据列出所有可访问的表(按schema分组)。Schema元数据列出表的列及元数据(类型/默认值/约束)。Schema元数据列出所有约束(PK/FK/UNIQUE/CHECK/EXCLUDE)。可按schema/表/类型过滤。Schema元数据列出所有外键关系。可按schema/表过滤。Schema元数据列出所有索引及定义和大小。可按schema/表过滤。Schema元数据列出已应用的数据库迁移记录。Schema元数据列出已安装的PostgreSQL扩展。

华为云官方博客 433

华为大数据Flink让每一 CU 算力,跑出开源 5.74 倍的性能

1. 开源Apache Flink 已成为业界流计算事实标准,但在极端重负载场景下存在性能瓶颈。2. 华为大数据Flink通过多项自研深度优化,在执行计划、算子执行、状态存储三个层面构建协同的优化体系。3. Nexmark Benchmark 测试结果:整体性能提升 5.74 倍,极端重负载场景性能领先最高 18.3 倍。4. 100% 兼容 Apache Flink 1.20,业务代码零改造,无缝迁移。

华为云官方博客 350

LakeAgent实战 | 业务分析篇从一句提问到业务分析

本文以“订单金额变化”分析为例,展示LakeAgent如何通过自然语言提问,结合DataArtsStudio的数据资产与专业技能,帮助业务人员快速定位数据、生成SQL、追踪血缘、生成报告。从问题出发,逐步实现数据发现、变化洞察、原因追溯与团队协作,最终形成可复用的分析流程与企业规则,显著提升数据分析效率与一致性。

华为云官方博客 358

华为云RDS Supabase AI应用已开放公测 :30分钟搭建AI应用后端

认证、存储、实时推送、数据库API——4个后端模块,传统开发需要数周。今天,你只需要30分钟。AI创业公司的全栈开发工程师。上周老板说"下周要上线的AI对话应用,后端你来搞"——认证鉴权、数据库接口、文件存储、实时推送,每一个模块都需要数周搭建,而市场不会等你。小张打开华为云RDS Supabase,30分钟搭好认证、数据库API、对象存储,剩下的时间全用来打磨AI交互体验。基于开源Supabase+华为云RDS PostgreSQL全托管能力,为开发者提供。

华为云官方博客 354

如何使用RDS Supabase后端BaaS能力:数据库函数(Database Function)

上一篇介绍了 Database Data API——建表即自动生成增删改查接口,解决单表读写,但聚合统计、跨表事务、字段自动维护等逻辑已超出其能力边界。本篇推进到数据库函数(Database Function):把业务逻辑封装进数据库,前端通过 .rpc() 调用,由触发器自动响应数据变更。上一篇中,小张基于 Data API 完成了产品目录的建表与基础读写。但新需求随之而来:按分类统计产品数与价格区间、上架新品同时写产品表与定价表、产品修改后自动刷新更新时间。

华为云官方博客 436

如何使用RDS Supabase后端BaaS能力:创表即生成API(Database Data API)

认证、存储、实时推送、数据库API——4个后端模块,传统开发要数周。本系列逐个拆解,首篇聚焦数据库API(Database Data API):建表即得 API,无需手写后端。小张,AI创业公司的全栈工程师。老板让他做个产品目录页,展示产品与价格、支持上下架。传统做法要搭后端、写接口、配权限,工期少说1-2周;而在华为云RDS Supabase,建两张表、应用 SDK 直连,几分钟增删改查全跑通。

华为云官方博客 453

从一句话到一个能出去的链接,AI开发者空间做了什么

自行搭建的 Agent、正在使用的开源项目、团队既有的工具,都可以接入,可以通过AI创建或者手动搭建环境;华为云 AI开发者空间——面向开发者的云端一站式开发平台,做的就是把这段路接上:环境免安装,浏览器打开即为完整的 Linux 运行环境,预置的 AI 智能体开箱即用。第一个任务建议选能出结果的:做一个游戏、生成一个页面、创建一台实例,从需求走到可访问的链接,一次就能看清这个环境在做什么。沙箱是一个完整的 Linux 环境,依赖、服务、端口都是真实的,不是模拟。环境释放后,权限随之失效。

华为云官方博客 411

华为云码道配置自定义大模型,四种方式完整实操

案例介绍。

华为云官方博客 604

图数据库:实现穿透式监管的数据基座

穿透式监管标志着国企监管从“管企业”向“管资本”转型过程中的关键一跃。而图数据库正是这一跃的技术支点。从股权穿透到资金链穿透,从供应链穿透到数据穿透,华为GES图数据库正在将“穿透式监管”从理念变为可落地、可操作的实践。无论是天眼查式的全量链路查询,还是某集团财经的税务规则判断,抑或是芯片供应链式的部件风险分析,乃至通过Palantir构建决策知识图谱,其底层逻辑都是一致的——用图的力量,穿透一切形式的“隔离层”,直抵风险本质与责任核心。

华为云官方博客 652

《公共云三十问》正式收官,奔赴企业AI百场景新征程

今年6月底,公共云产业联盟重点推出《公共云三十问》专栏,以每周三问的节奏,连载十周,解读《先进公共云》白皮书,分享国计民生系列案例,旨在凝聚共识、推动落地实践。同时,专栏分析公共云在产业升级、民生福祉、科技创新、全球发展等方面的作用,梳理中国特色公共云发展路径:以普惠云拓展用云广度,以智算云提升用云深度,以自主云夯实用云厚度,以全球云打开用云跨度。这十问从专属云、行业云切入,深入政务、金融、交通、电力、钢铁、化工、油气、制造等国计民生场景,回答公共云“怎么用”。

华为云官方博客 465

开发者小技巧|IAM配置,让码道代码智能体连续30天免登录

案例介绍。

华为云官方博客 640

码道深度对接CodeArts,让需求自动落地为代码

案例介绍。

华为云官方博客 712

【公共云三十问 之三十】拥抱AI,企业如何建设面向智能体的专属云?

企业可分阶段建设覆盖开发、运行、运营及安全的一体化智能体平台——从构建一站式、高低码协同的智能体开发平台,到打造高性能、极致弹性的运行时环境,再到搭建AgentOps驱动的持续运营与运维体系,同时构建端到端、多层次的全链路安全防护体系。在数据湖建设方面,遵循“存量复用、平滑演进、AI导向、分步迭代”原则,分三阶段推进——打造AI多模数据湖核心能力、完成存算分离与统一元数据管理、实现闭环赋能全面支撑智能体规模化落地,在保护既有投资的前提下将传统数据平台转型为AI数据专属供给平台。

华为云官方博客 818

【公共云三十问 之二十九】国计民生之制造:制造云如何重塑数智时代的新质生产力?

平台打通软件交付的完整路径,覆盖需求管理、代码托管、代码检查、编译构建、制品仓库、部署、测试等关键环节,支持大模型能力融入研发全流程,实现从需求到交付的端到端管理。通过构建“研发一朵云”,方案打破地域与组织壁垒,实现跨团队协同开发,有效缩短软件交付周期,助力工业制造企业从“传统研发”走向“敏捷研发”,加速数智化转型进程。当制造云真正成为数据流通的平台、AI创新的底座,公共云的社会价值将从基础设施层向生产场景层持续延伸,为新型工业化建设和制造强国战略注入源源不断的动力,重塑数智时代的中国制造新质生产力。

华为云官方博客 786

告别重复手工迁仓,码道MCP+Skill实现仓库批量迁移

案例介绍。

华为云官方博客 781

【公共云三十问 之二十八】国计民生之油气:智算云如何叩响数智时代的“地心蓝金”?

西南油气田以“向地球深部要资源”为战略方向,联合以华为云Stack为代表的公共云服务商共同打造统一算力底座,建设西南区域数据湖与通用技术平台,构建“勘探开发工程技术、天然气生产过程管控、天然气产运储销”等三个一体化协同应用场景,支撑油气勘探、开发生产、管输储运等全业务链的数智化转型。当智算云真正成为数据流通的平台、AI创新的底座,油气田得以将算力效能、数据价值与智能技术深度融入勘探开发全链条,将“看不见的算力”转化为“摸得着的储量”,以智能化手段持续降低勘探风险、缩短发现周期、提高采收效率,确保生产安全。

华为云官方博客 612

【公共云三十问 之二十七】国计民生之化工:数智云如何重塑传统化工新范式?

在架构方面,方案构建云边协同的统一体系,涵盖AI协同、数据协同与运营协同三大维度——总部集中训练大模型,边缘节点负责推理执行,云边持续迭代,实现“边用边学”的智能闭环,模型平均精度提升20%以上。此外,方案提供一站式企业级工业物联网平台、数据湖与数据治理平台,覆盖工业数据分析“采、存、算、管、用”全流程,打通生产现场与管理系统间的数据壁垒,有效消除数据孤岛。层面,方案充分发挥软硬协同优势,实现计算、存储、网络与云平台的深度协同,训练线性度超95%,为大模型训练推理提供强劲算力支撑。▲化工“数智”新模式。

华为云官方博客 663

【公共云三十问 之二十六】国计民生之钢铁:数智云如何淬炼中国钢铁新力量?

同时,构建云边端协同的统一架构,支撑集团总部与各生产基地两级协同发展——总部集中训练大模型,边缘节点负责推理执行,云边持续迭代,实现训推一体化的资源调度与高效协同,为钢铁行业的数智化转型构建了坚实的算力底座。层面,方案构建覆盖“工业数采→边缘IT/OT融合→统一数据湖→数据治理平台→数据应用”全链路的一站式数据治理与流通平台,打通生产现场与管理系统间的数据壁垒,让数据“采得到、流得动、用得好”,加速数据价值从生产现场向经营决策层流动释放。湘潭钢铁集团的钢铁数智云,是钢铁工业智能云建设的标杆案例。

华为云官方博客 524

LakeWatch——MRS 智能运维Agent

从资源池、队列、作业等多个维度,对集群CPU与内存资源进行精细化分析与对比,直观呈现不同时间段的空闲、满载等使用状态,识别资源浪费,指导治理优化,为扩缩容决策提供数据支撑。对HDFS存储进行多维度深度分析(目录、用户、用户组等),涵盖使用量、增量、文件大小分布及数据热度等指标,帮助快速识别增长较快的目录、长期未访问的文件,统计目录文件数量与小文件占比,评估HDFS总存储量与扩缩容需求,为存储治理与资源规划提供全面数据支撑。Agent主动巡检,识别异常趋势并提前预警,让运维从"事后处理"转向"事前预防"。

华为云官方博客 511

华为云专题文档发布:丰富的AI案例、选型指导和概念解读

发布 “云服务选型”、“云计算概念”专题,提供云服务选型指导,助您选择匹配业务的云服务,解读云计算相关概念,开启云上学习之路。开发者工具和文档专区上线,提供从学习、实践到反馈的全链路支持。帮助中心新增100余篇AI案例。

华为云官方博客 286

一个人,也能用AI做点“星东西”

华为云星耀创想者大赛-2026华为云OPC创意大赛等你来~

华为云官方博客 289

从需求到可执行工作项:MCP+Skill 让智能体规划真正落地

回顾整个体验,以前让智能体帮我拆需求,它是洋洋洒洒给我列了一大篇 Markdown,看着挺像那么回事,但最后还是得我一条条往 CodeArts Req 里搬,搬完再手动挂父子关系、排日期,拆需求五分钟,搬运两小时。现在好了,MCP 给智能体接上了"手",Skill 给它装上了"项目经理的脑子",一句话下去,34 个工作项连带排期、层级关系全给我建好了,甘特图一拉,齐刷刷都在两周内,节省了多少工作量啊,美滋滋。本次实操在码道代码智能体基础上,构建了一套"需求→可执行工作项"的自动化规划方案。

华为云官方博客 561

华为云码道「码力续航计划」更新!

✅上新GLM‑5.3‑Flash,高速响应,代码生成、工程解析、Agent调试高效输出。新增GLM‑5.3‑Flash福利模型,每日解锁1000万免费Tokens。● 本次活动共发放总量价值100万元Tokens,发完即止!把耗算力的编码重活,交给华为云码道代码智能体🚀🚀。● 每日额度准时刷新,当日清零、次日满血重置。✅复杂算法、大项目解析、批量代码生成随便跑。✅不用抠额度、不用算消耗,放开调试大胆迭代。✅无需额外操作,登录即送,直接切换模型使用。● 把算力交给码道,让撸码不再内耗👏🏻。

华为云官方博客 677

【公共云三十问 之二十四】国计民生之交通:交通云如何铺就数智通衢新坦途?

交通行业作为支撑实体经济的关键基础设施,涵盖公路、铁路、机场、港口、地铁等众多子领域,其中,公路网络作为综合交通运输体系的基础骨架,承担着全国超过70%的客货运量,其数字化、智能化转型的需求尤为迫切。方面,提供Agent开发框架、知识库管理、RAG工程、意图识别、静态应用编排及模型评测等能力,支持客户将行业知识、业务流程与AI能力深度融合,快速构建面向收费稽核、路网调度、应急处置等场景的智能应用。开发并实现落地应用,全面覆盖建设、管理、养护、运营、服务、安全、办公七大业务领域。

华为云官方博客 460

【公共云三十问 之二十五】国计民生之电力:电力云如何点亮数智电力新引擎?

方案构建了覆盖数据获取、质量评估到标准化处理的全链路能力。基于公共云服务商智算底座及气象大模型,通过时空图神经网络重新建模产流机制,中国华电建成超50TB多源融合数据集,突破时空建模与机理融合等五大关键技术,短期径流预测精度较传统机理模型提升5个百分点以上,实现15天中期径流预测精度超85%,推理效率达秒级。基于气象大模型的基础架构与预训练能力,客户可直接在大模型之上开展增量训练与微调,充分利用场站所在区域的高精度历史数据(如3公里、1公里分辨率),针对不同场站和区域的地形地貌与气候特征进行模型调优。

华为云官方博客 380

邀请函|第三届“兴智杯”全国人工智能创新应用大赛开幕式,期待您现场莅临

AI 算法工程师、大模型应用开发、智能编码、国产软硬件栈开发者、开源开发者。大赛官方参赛对象就包含企事业单位开发者团队、个人开发者中华人民共...诉求:了解本届赛题方向、对接算力 / 技术资源、认识同行、获取参赛信息。意向参赛团队、往届参赛选手、技术团队负责人、个人独立开发者。

华为云官方博客 478
上一篇: MRS大企业ERP流程实时数据湖加工最佳实践
下一篇: BeanDefinition解密:构建和管理Spring Beans的基石
华为云开发者联盟
华为云开发者联盟 企业官方账号 企业官方账号
博客等级 码龄10年 72万+粉丝 5984原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值