Skip to content

Commit a9315af

Browse files
author
Justin Iurman
authored
Merge pull request #3 from Advanced-Observability/clt_genl_go
CLT netlink Go
2 parents 506fa5d + 8356e17 commit a9315af

9 files changed

Lines changed: 268 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The chosen Application Performance Management (APM) tool based on distributed tr
1010

1111
Some key components are crucial for the CLT ecosystem:
1212
- a recent kernel with IOAM (>= 5.17) [patched](./CLT.patch) for Cross-Layer Telemetry
13-
- the CLT [client library](./clt_genl.py)
13+
- the CLT client library in [Python](./clt_genl.py) or in [Go](./clt_genl_go/)
1414
- an [IOAM Agent](https://github.com/Advanced-Observability/ioam-agent-python/tree/clt)
1515
- an [IOAM Collector](https://github.com/Advanced-Observability/ioam-collector-go-jaeger)
1616

demo/docker/athos/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ RUN pip install -q itsdangerous==2.0.1
2727
WORKDIR /apps
2828
COPY app.py app.py
2929
COPY supervisord.conf supervisord.conf
30-
RUN wget https://raw.githubusercontent.com/Advanced-Observability/cross-layer-telemetry/main/clt_genl.py
30+
RUN wget https://raw.githubusercontent.com/Advanced-Observability/cross-layer-telemetry/main/library/python/clt_genl.py
3131

3232
EXPOSE 15123
3333

library/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# CLT Library
2+
3+
This library allows to enable or disable CLT in the Linux kernel by using [generic netlink](https://docs.kernel.org/networking/generic_netlink.html) to interact with the kernel.
4+
5+
## Usage
6+
7+
The implementations **must** provide 2 methods:
8+
- One to **enable** CLT on a given socket with given trace and span IDs.
9+
- One to **disable** CLT on a given socket.
10+
11+
## Existing implementations
12+
13+
At the moment, implementations are available in the following languages:
14+
- [Python](./python/)
15+
- [Go](./golang/)

library/golang/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# CLT Library in Go
2+
3+
Implementation in Go of the library to enable or disable CLT.
4+
5+
## Usage
6+
7+
First, you need to download the dependencies with the following command:
8+
```bash
9+
go mod download
10+
```
11+
12+
Then, you can enable CLT on a socket using the method:
13+
```go
14+
func clt_enable(socketFD uint32, traceIDHigh uint64, traceIDLow uint64, spanID uint64) error
15+
```
16+
17+
Finally, when you want to disable CLT, you can use the method:
18+
```go
19+
func clt_disable(socketFD uint32) error
20+
```
21+
22+
## Credits
23+
24+
To use (generic) netlink in Go, we use the packages [netlink](https://github.com/mdlayher/netlink) and [genetlink](https://github.com/mdlayher/genetlink) by [Matt Layher](https://github.com/mdlayher).

library/golang/clt_genl.go

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Module to enable or disable CLT in the kernel by using generic netlink
2+
3+
package clt_genl
4+
5+
import (
6+
"errors"
7+
"fmt"
8+
"log"
9+
"os"
10+
11+
"github.com/mdlayher/genetlink"
12+
"github.com/mdlayher/netlink"
13+
"github.com/mdlayher/netlink/nlenc"
14+
)
15+
16+
// Family name
17+
const IOAM6_GENL_NAME string = "IOAM6"
18+
19+
// Attributes
20+
const IOAM6_ATTR_SOCKFD uint16 = 8
21+
const IOAM6_ATTR_ID_HIGH uint16 = 9
22+
const IOAM6_ATTR_ID_LOW uint16 = 10
23+
const IOAM6_ATTR_SUBID uint16 = 11
24+
25+
// Commands
26+
const IOAM6_CMD_PKT_ID_ENABLE uint8 = 8
27+
const IOAM6_CMD_PKT_ID_DISABLE uint8 = 9
28+
29+
/*
30+
Create socket for IOAM6 generic netlink and get the IOAM6 generic netlink family.
31+
32+
Return:
33+
- Created connection if no error. Else, nil.
34+
- IOAM6 generic netlink family if no error. Else, empty family.
35+
- Error if any. Else, nil.
36+
*/
37+
func ioam6_generic_netlink() (*genetlink.Conn, genetlink.Family, error) {
38+
// Create generic netlink socket to interact with kernel
39+
c, err := genetlink.Dial(nil)
40+
if err != nil {
41+
log.Printf("failed to dial generic netlink: %v\n", err)
42+
return nil, genetlink.Family{}, err
43+
}
44+
45+
// Get family because depending on kernel the id for the family can change
46+
family, err := c.GetFamily(IOAM6_GENL_NAME)
47+
if err != nil {
48+
if errors.Is(err, os.ErrNotExist) {
49+
log.Printf("%q family not available", IOAM6_GENL_NAME)
50+
return nil, genetlink.Family{}, err
51+
}
52+
53+
log.Fatalf("failed to query for family: %v", err)
54+
}
55+
56+
return c, family, nil
57+
}
58+
59+
/*
60+
Enable CLT on the given socket for the given trace and span ids.
61+
62+
Parameters:
63+
- socketFD: socket on which to enable clt
64+
- traceIDHigh: MSB of trace id
65+
- traceIDLow: LSB of trace id
66+
- spanID: span id
67+
68+
Return:
69+
Error if any. Else, nil.
70+
*/
71+
func clt_enable(socketFD uint32, traceIDHigh uint64, traceIDLow uint64, spanID uint64) error {
72+
c, family, err := ioam6_generic_netlink()
73+
if err != nil {
74+
fmt.Println("Error while establishing generic netlink socket")
75+
return err
76+
}
77+
defer c.Close()
78+
79+
// Create attributes for the request
80+
b, err := netlink.MarshalAttributes([]netlink.Attribute{
81+
{
82+
Type: IOAM6_ATTR_SOCKFD,
83+
Data: nlenc.Uint32Bytes(socketFD),
84+
},
85+
{
86+
Type: IOAM6_ATTR_ID_HIGH,
87+
Data: nlenc.Uint64Bytes(traceIDHigh),
88+
},
89+
{
90+
Type: IOAM6_ATTR_ID_LOW,
91+
Data: nlenc.Uint64Bytes(traceIDLow),
92+
},
93+
{
94+
Type: IOAM6_ATTR_SUBID,
95+
Data: nlenc.Uint64Bytes(spanID),
96+
},
97+
})
98+
if err != nil {
99+
fmt.Println("Cannot create attributes for generic netlink message")
100+
return err
101+
}
102+
103+
// Create message with headers + attributes
104+
req := genetlink.Message{
105+
Header: genetlink.Header{
106+
Command: IOAM6_CMD_PKT_ID_ENABLE,
107+
Version: uint8(family.Version),
108+
},
109+
Data: b,
110+
}
111+
112+
// Send message
113+
flags := netlink.Request | netlink.Acknowledge
114+
if _, err = c.Execute(req, family.ID, flags); err != nil {
115+
fmt.Println("clt_enable execute error: " + err.Error())
116+
return err
117+
}
118+
119+
return nil
120+
}
121+
122+
/*
123+
Disable CLT on the given socket.
124+
125+
Parameters:
126+
- socketFD: socket on which to disable clt
127+
128+
Return:
129+
Error if any. Else, nil.
130+
*/
131+
func clt_disable(socketFD uint32) error {
132+
c, family, err := ioam6_generic_netlink()
133+
if err != nil {
134+
fmt.Println("Error while establishing generic netlink socket")
135+
return err
136+
}
137+
defer c.Close()
138+
139+
// Create attributes for the request
140+
b, err := netlink.MarshalAttributes([]netlink.Attribute{
141+
{
142+
Type: IOAM6_ATTR_SOCKFD,
143+
Data: nlenc.Uint32Bytes(socketFD),
144+
},
145+
})
146+
if err != nil {
147+
fmt.Println("Cannot create attributes for generic netlink message")
148+
return err
149+
}
150+
151+
// Create message with headers + attributes
152+
req := genetlink.Message{
153+
Header: genetlink.Header{
154+
Command: IOAM6_CMD_PKT_ID_DISABLE,
155+
Version: uint8(family.Version),
156+
},
157+
Data: b,
158+
}
159+
160+
// Send message
161+
flags := netlink.Request | netlink.Acknowledge
162+
if _, err = c.Execute(req, family.ID, flags); err != nil {
163+
fmt.Println("clt_disable execute error: " + err.Error())
164+
return err
165+
}
166+
167+
return nil
168+
}

library/golang/go.mod

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module clt_genl
2+
3+
go 1.21.4
4+
5+
require (
6+
github.com/mdlayher/genetlink v1.3.2
7+
github.com/mdlayher/netlink v1.7.2
8+
)
9+
10+
require (
11+
github.com/google/go-cmp v0.6.0 // indirect
12+
github.com/josharian/native v1.1.0 // indirect
13+
github.com/mdlayher/socket v0.4.1 // indirect
14+
golang.org/x/net v0.9.0 // indirect
15+
golang.org/x/sync v0.1.0 // indirect
16+
golang.org/x/sys v0.14.0 // indirect
17+
)

library/golang/go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
2+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3+
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
4+
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
5+
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
6+
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
7+
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
8+
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
9+
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
10+
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
11+
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
12+
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
13+
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
14+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
15+
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
16+
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

library/python/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# CLT Library in Python
2+
3+
Implementation in Python of the library to enable or disable CLT.
4+
5+
## Usage
6+
7+
First, you need to download the dependency with the following command:
8+
```bash
9+
pip3 install pyroute2
10+
```
11+
12+
Then, you need to create an instance of the class `CrossLayerTelemetry`.
13+
14+
Now, you can enable CLT on a socket by calling the method:
15+
```python
16+
def enable(self, sockfd, traceId, spanId)
17+
```
18+
19+
Finally, when you want to disable CLT, you can call the method:
20+
```python
21+
def disable(self, sockfd)
22+
```
23+
24+
## Credits
25+
26+
To use (generic) netlink in Python, we use the package [pyroute2](https://pypi.org/project/pyroute2/) by [Peter Saveliev](https://github.com/svinota).
File renamed without changes.

0 commit comments

Comments
 (0)