Skip to content

Commit 69d953f

Browse files
committed
Refactor netlink message
Signed-off-by: Ze Gan <[email protected]>
1 parent 31a2049 commit 69d953f

File tree

1 file changed

+79
-9
lines changed

1 file changed

+79
-9
lines changed

doc/high-frequency-telemetry/high-frequency-telemetry-hld.md

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,45 @@ The IPFIX template should be provided by vendors. This document does not restric
392392

393393
#### 7.2.4. Netlink message
394394

395-
We expect all control messages and out-of-band information to be transmitted by the SAI. Therefore, it is unnecessary to read the attribute header of netlink and the message header of Genetlink from the socket. Instead, we can insert a bulk of IPFIX recordings as the payload of the netlink message. The sample code for building the message from the kernel side is as follows:
395+
The netlink message consists of a netlink header, a genetlink header, and IPFIX message as the payload. All control messages and out-of-band information are transmitted by the SAI. The IPFIX recordings are directly placed as the payload without additional netlink attributes.
396+
397+
The message structure is as follows:
398+
399+
``` mermaid
400+
401+
---
402+
title: Netlink message structure
403+
---
404+
packet-beta
405+
0-31: "nlmsg_len: 16+4+payload length"
406+
32-47: "nlmsg_type: family ID"
407+
48-63: "nlmsg_flags: 0x0000"
408+
64-95: "nlmsg_seq: 0x00000000"
409+
96-127: "nlmsg_pid: 0x00000000"
410+
128-135: "cmd: 0x00"
411+
136-143: "version: protocol version"
412+
144-159: "reserved: 0x0000"
413+
160-191: "IPFIX Message Payload"
414+
192-223: "..."
415+
416+
```
417+
418+
**Netlink Header (16 bytes):**
419+
- `nlmsg_len` (4 bytes): Total message length including headers = 16 (nlheader) + 4 (genheader) + payload length
420+
- `nlmsg_type` (2 bytes): Message type = family ID (assigned by kernel when family is registered)
421+
- `nlmsg_flags` (2 bytes): Message flags = 0x0000 (no special flags for multicast data)
422+
- `nlmsg_seq` (4 bytes): Sequence number = 0x00000000 (not used for multicast messages)
423+
- `nlmsg_pid` (4 bytes): Process ID = 0x00000000 (kernel originated message)
424+
425+
**Generic Netlink Header (4 bytes):**
426+
- `cmd` (1 byte): Command type = 0x00 (always 0)
427+
- `version` (1 byte): Protocol version (implementation dependent)
428+
- `reserved` (2 bytes): Reserved for future use = 0x0000
429+
430+
**IPFIX Message Payload:**
431+
- Direct IPFIX message content without netlink attributes
432+
433+
The sample code for building the message from the kernel side is as follows:
396434

397435
``` c
398436

@@ -409,21 +447,53 @@ static struct genl_family stel_family = {
409447
.n_mcgrps = ARRAY_SIZE(stel_mcgrps),
410448
};
411449

450+
#define STEL_CMD_IPFIX_DATA 0
412451

413452
void send_msgs_to_user(/* ... */)
414453
{
415-
struct sk_buff *skb_out = nlmsg_new(ipfix_msg_len, GFP_KERNEL);
416-
417-
for (size_t i = 0; i < bulk_count; i++)
418-
{
454+
struct sk_buff *skb_out;
455+
void *msg_head;
456+
size_t total_ipfix_len = 0;
457+
458+
// Calculate total IPFIX payload length
459+
for (size_t i = 0; i < bulk_count; i++) {
460+
struct ipfix *msg = ring_buffer.peek(i);
461+
if (msg == NULL) {
462+
break;
463+
}
464+
total_ipfix_len += msg->len;
465+
}
466+
467+
// Allocate netlink message (netlink header + genetlink header + IPFIX payload)
468+
skb_out = nlmsg_new(GENL_HDRLEN + total_ipfix_len, GFP_KERNEL);
469+
if (!skb_out) {
470+
return;
471+
}
472+
473+
// Add genetlink header with cmd = 0
474+
msg_head = genlmsg_put(skb_out, 0, 0, &stel_family, 0, STEL_CMD_IPFIX_DATA);
475+
if (!msg_head) {
476+
nlmsg_free(skb_out);
477+
return;
478+
}
479+
480+
// Append IPFIX messages directly as payload (no netlink attributes)
481+
for (size_t i = 0; i < bulk_count; i++) {
419482
struct ipfix *msg = ring_buffer.pop();
420-
if (msg == NULL)
421-
{
483+
if (msg == NULL) {
484+
break;
485+
}
486+
// Directly append IPFIX data to the skb
487+
if (skb_put_data(skb_out, msg->data, msg->len) != 0) {
488+
// Handle error
422489
break;
423490
}
424-
nla_append(skb_out, msg->data, msg->len);
425491
}
426-
492+
493+
// Finalize the message
494+
genlmsg_end(skb_out, msg_head);
495+
496+
// Send to multicast group
427497
genlmsg_multicast(&stel_family, skb_out, 0, 0/* group_id to ipfix group */, GFP_KERNEL);
428498
}
429499

0 commit comments

Comments
 (0)