conlink 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +5 -0
- package/Dockerfile +34 -0
- package/LICENSE +373 -0
- package/README.md +485 -0
- package/TODO +34 -0
- package/conlink +11 -0
- package/conlink-start.sh +172 -0
- package/examples/dot.js +36 -0
- package/examples/index.html +11 -0
- package/examples/net2dot.yaml +21 -0
- package/examples/test1-compose.yaml +60 -0
- package/examples/test2-compose.yaml +31 -0
- package/examples/test2-network.yaml +5 -0
- package/examples/test3-network.yaml +5 -0
- package/examples/test4-multiple/all-compose.yaml +5 -0
- package/examples/test4-multiple/base-compose.yaml +25 -0
- package/examples/test4-multiple/node1-compose.yaml +17 -0
- package/examples/test4-multiple/nodes2-compose.yaml +20 -0
- package/examples/test4-multiple/web-network.yaml +2 -0
- package/examples/test5-geneve-compose.yaml +31 -0
- package/examples/test6-cfn.yaml +184 -0
- package/examples/test7-compose.yaml +31 -0
- package/examples/test8-compose.yaml +35 -0
- package/host-build.yaml +1 -0
- package/inspect.json +210 -0
- package/link-add.sh +197 -0
- package/link-del.sh +60 -0
- package/net2dot +11 -0
- package/notes.txt +82 -0
- package/old/Dockerfile.bak +26 -0
- package/old/add-link.sh +82 -0
- package/old/conlink +12 -0
- package/old/conlink.cljs +131 -0
- package/old/dot_gitignore +1 -0
- package/old/examples/test2-compose.yaml +32 -0
- package/old/examples/test2-network.yaml +42 -0
- package/old/move-link.sh +108 -0
- package/old/net2dot.py +122 -0
- package/old/notes-old.txt +97 -0
- package/old/package.json +16 -0
- package/old/schema.yaml +138 -0
- package/old/schema.yaml.bak +76 -0
- package/old/test2b-compose.yaml +18 -0
- package/old/veth-link.sh +96 -0
- package/package.json +15 -0
- package/schema-ish.yaml +29 -0
- package/schema.yaml +71 -0
- package/shadow-cljs.edn +33 -0
- package/src/conlink/addrs.cljc +63 -0
- package/src/conlink/core.cljs +772 -0
- package/src/conlink/net2dot.cljs +158 -0
- package/src/conlink/util.cljs +140 -0
- package/tests/invalid-schema-1.yaml +6 -0
- package/tests/invalid-schema-2.yaml +6 -0
- package/tests/invalid-schema-3.yaml +17 -0
- package/tests/invalid-schema-4.yaml +14 -0
- package/tests/invalid-schema-5.yaml +12 -0
- package/tests/invalid-schema-6.yaml +12 -0
- package/tmp/conlink/.env +1 -0
package/inspect.json
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"Id": "43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357",
|
|
4
|
+
"Created": "2023-10-11T15:55:04.428835024Z",
|
|
5
|
+
"Path": "sh",
|
|
6
|
+
"Args": [
|
|
7
|
+
"-c",
|
|
8
|
+
"while ! ip link show eth0 up; do sleep 1; done; sleep 864000"
|
|
9
|
+
],
|
|
10
|
+
"State": {
|
|
11
|
+
"Status": "running",
|
|
12
|
+
"Running": true,
|
|
13
|
+
"Paused": false,
|
|
14
|
+
"Restarting": false,
|
|
15
|
+
"OOMKilled": false,
|
|
16
|
+
"Dead": false,
|
|
17
|
+
"Pid": 10216,
|
|
18
|
+
"ExitCode": 0,
|
|
19
|
+
"Error": "",
|
|
20
|
+
"StartedAt": "2023-10-11T15:55:04.576997181Z",
|
|
21
|
+
"FinishedAt": "0001-01-01T00:00:00Z"
|
|
22
|
+
},
|
|
23
|
+
"Image": "sha256:8ca4688f4f356596b5ae539337c9941abc78eda10021d35cbc52659c74d9b443",
|
|
24
|
+
"ResolvConfPath": "/var/lib/docker/containers/43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357/resolv.conf",
|
|
25
|
+
"HostnamePath": "/var/lib/docker/containers/43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357/hostname",
|
|
26
|
+
"HostsPath": "/var/lib/docker/containers/43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357/hosts",
|
|
27
|
+
"LogPath": "/var/lib/docker/containers/43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357/43e63a3c948443f55198f4de29fd96805fdb306398ff64d89f1103c355e28357-json.log",
|
|
28
|
+
"Name": "/examples_node2_1",
|
|
29
|
+
"RestartCount": 0,
|
|
30
|
+
"Driver": "overlay2",
|
|
31
|
+
"Platform": "linux",
|
|
32
|
+
"MountLabel": "",
|
|
33
|
+
"ProcessLabel": "",
|
|
34
|
+
"AppArmorProfile": "docker-default",
|
|
35
|
+
"ExecIDs": null,
|
|
36
|
+
"HostConfig": {
|
|
37
|
+
"Binds": [],
|
|
38
|
+
"ContainerIDFile": "",
|
|
39
|
+
"LogConfig": {
|
|
40
|
+
"Type": "json-file",
|
|
41
|
+
"Config": {}
|
|
42
|
+
},
|
|
43
|
+
"NetworkMode": "none",
|
|
44
|
+
"PortBindings": {},
|
|
45
|
+
"RestartPolicy": {
|
|
46
|
+
"Name": "",
|
|
47
|
+
"MaximumRetryCount": 0
|
|
48
|
+
},
|
|
49
|
+
"AutoRemove": false,
|
|
50
|
+
"VolumeDriver": "",
|
|
51
|
+
"VolumesFrom": [],
|
|
52
|
+
"ConsoleSize": [
|
|
53
|
+
0,
|
|
54
|
+
0
|
|
55
|
+
],
|
|
56
|
+
"CapAdd": [
|
|
57
|
+
"NET_ADMIN"
|
|
58
|
+
],
|
|
59
|
+
"CapDrop": null,
|
|
60
|
+
"CgroupnsMode": "host",
|
|
61
|
+
"Dns": null,
|
|
62
|
+
"DnsOptions": null,
|
|
63
|
+
"DnsSearch": null,
|
|
64
|
+
"ExtraHosts": null,
|
|
65
|
+
"GroupAdd": null,
|
|
66
|
+
"IpcMode": "private",
|
|
67
|
+
"Cgroup": "",
|
|
68
|
+
"Links": null,
|
|
69
|
+
"OomScoreAdj": 0,
|
|
70
|
+
"PidMode": "",
|
|
71
|
+
"Privileged": false,
|
|
72
|
+
"PublishAllPorts": false,
|
|
73
|
+
"ReadonlyRootfs": false,
|
|
74
|
+
"SecurityOpt": null,
|
|
75
|
+
"UTSMode": "",
|
|
76
|
+
"UsernsMode": "",
|
|
77
|
+
"ShmSize": 67108864,
|
|
78
|
+
"Runtime": "runc",
|
|
79
|
+
"Isolation": "",
|
|
80
|
+
"CpuShares": 0,
|
|
81
|
+
"Memory": 0,
|
|
82
|
+
"NanoCpus": 0,
|
|
83
|
+
"CgroupParent": "",
|
|
84
|
+
"BlkioWeight": 0,
|
|
85
|
+
"BlkioWeightDevice": null,
|
|
86
|
+
"BlkioDeviceReadBps": null,
|
|
87
|
+
"BlkioDeviceWriteBps": null,
|
|
88
|
+
"BlkioDeviceReadIOps": null,
|
|
89
|
+
"BlkioDeviceWriteIOps": null,
|
|
90
|
+
"CpuPeriod": 0,
|
|
91
|
+
"CpuQuota": 0,
|
|
92
|
+
"CpuRealtimePeriod": 0,
|
|
93
|
+
"CpuRealtimeRuntime": 0,
|
|
94
|
+
"CpusetCpus": "",
|
|
95
|
+
"CpusetMems": "",
|
|
96
|
+
"Devices": null,
|
|
97
|
+
"DeviceCgroupRules": null,
|
|
98
|
+
"DeviceRequests": null,
|
|
99
|
+
"MemoryReservation": 0,
|
|
100
|
+
"MemorySwap": 0,
|
|
101
|
+
"MemorySwappiness": null,
|
|
102
|
+
"OomKillDisable": false,
|
|
103
|
+
"PidsLimit": null,
|
|
104
|
+
"Ulimits": null,
|
|
105
|
+
"CpuCount": 0,
|
|
106
|
+
"CpuPercent": 0,
|
|
107
|
+
"IOMaximumIOps": 0,
|
|
108
|
+
"IOMaximumBandwidth": 0,
|
|
109
|
+
"MaskedPaths": [
|
|
110
|
+
"/proc/asound",
|
|
111
|
+
"/proc/acpi",
|
|
112
|
+
"/proc/kcore",
|
|
113
|
+
"/proc/keys",
|
|
114
|
+
"/proc/latency_stats",
|
|
115
|
+
"/proc/timer_list",
|
|
116
|
+
"/proc/timer_stats",
|
|
117
|
+
"/proc/sched_debug",
|
|
118
|
+
"/proc/scsi",
|
|
119
|
+
"/sys/firmware"
|
|
120
|
+
],
|
|
121
|
+
"ReadonlyPaths": [
|
|
122
|
+
"/proc/bus",
|
|
123
|
+
"/proc/fs",
|
|
124
|
+
"/proc/irq",
|
|
125
|
+
"/proc/sys",
|
|
126
|
+
"/proc/sysrq-trigger"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
"GraphDriver": {
|
|
130
|
+
"Data": {
|
|
131
|
+
"LowerDir": "/var/lib/docker/overlay2/f45757baf87c92f0934409fa9617bd4027e1e4472711312b1d8145ca59cdf0f3-init/diff:/var/lib/docker/overlay2/0ee1adfcd9b69bb9354db86819da1c06904d5c664f8d9e0aded8c158a24654df/diff",
|
|
132
|
+
"MergedDir": "/var/lib/docker/overlay2/f45757baf87c92f0934409fa9617bd4027e1e4472711312b1d8145ca59cdf0f3/merged",
|
|
133
|
+
"UpperDir": "/var/lib/docker/overlay2/f45757baf87c92f0934409fa9617bd4027e1e4472711312b1d8145ca59cdf0f3/diff",
|
|
134
|
+
"WorkDir": "/var/lib/docker/overlay2/f45757baf87c92f0934409fa9617bd4027e1e4472711312b1d8145ca59cdf0f3/work"
|
|
135
|
+
},
|
|
136
|
+
"Name": "overlay2"
|
|
137
|
+
},
|
|
138
|
+
"Mounts": [],
|
|
139
|
+
"Config": {
|
|
140
|
+
"Hostname": "43e63a3c9484",
|
|
141
|
+
"Domainname": "",
|
|
142
|
+
"User": "",
|
|
143
|
+
"AttachStdin": false,
|
|
144
|
+
"AttachStdout": false,
|
|
145
|
+
"AttachStderr": false,
|
|
146
|
+
"Tty": false,
|
|
147
|
+
"OpenStdin": false,
|
|
148
|
+
"StdinOnce": false,
|
|
149
|
+
"Env": [
|
|
150
|
+
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
151
|
+
],
|
|
152
|
+
"Cmd": [
|
|
153
|
+
"sh",
|
|
154
|
+
"-c",
|
|
155
|
+
"while ! ip link show eth0 up; do sleep 1; done; sleep 864000"
|
|
156
|
+
],
|
|
157
|
+
"Image": "alpine",
|
|
158
|
+
"Volumes": null,
|
|
159
|
+
"WorkingDir": "",
|
|
160
|
+
"Entrypoint": null,
|
|
161
|
+
"OnBuild": null,
|
|
162
|
+
"Labels": {
|
|
163
|
+
"com.docker.compose.config-hash": "be458eaf2e2aba67235023be9f8342d88ce0e0f7979749d6496423229a954bd3",
|
|
164
|
+
"com.docker.compose.container-number": "1",
|
|
165
|
+
"com.docker.compose.oneoff": "False",
|
|
166
|
+
"com.docker.compose.project": "examples",
|
|
167
|
+
"com.docker.compose.project.config_files": "examples/test2-compose.yaml",
|
|
168
|
+
"com.docker.compose.project.working_dir": "/home/jmartin/work/viasat/repos/conlink.cljs/examples",
|
|
169
|
+
"com.docker.compose.service": "node2",
|
|
170
|
+
"com.docker.compose.version": "1.29.2"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"NetworkSettings": {
|
|
174
|
+
"Bridge": "",
|
|
175
|
+
"SandboxID": "963251cd8230a51e9c658653a3fdeedfe10e9f16c03aed802b69d5a6c86f6d19",
|
|
176
|
+
"HairpinMode": false,
|
|
177
|
+
"LinkLocalIPv6Address": "",
|
|
178
|
+
"LinkLocalIPv6PrefixLen": 0,
|
|
179
|
+
"Ports": {},
|
|
180
|
+
"SandboxKey": "/var/run/docker/netns/963251cd8230",
|
|
181
|
+
"SecondaryIPAddresses": null,
|
|
182
|
+
"SecondaryIPv6Addresses": null,
|
|
183
|
+
"EndpointID": "",
|
|
184
|
+
"Gateway": "",
|
|
185
|
+
"GlobalIPv6Address": "",
|
|
186
|
+
"GlobalIPv6PrefixLen": 0,
|
|
187
|
+
"IPAddress": "",
|
|
188
|
+
"IPPrefixLen": 0,
|
|
189
|
+
"IPv6Gateway": "",
|
|
190
|
+
"MacAddress": "",
|
|
191
|
+
"Networks": {
|
|
192
|
+
"none": {
|
|
193
|
+
"IPAMConfig": null,
|
|
194
|
+
"Links": null,
|
|
195
|
+
"Aliases": null,
|
|
196
|
+
"NetworkID": "c7b50bdae4d8c2baa2dfbfcf81a783cddcfd66df84c6ce3f3506985434a161c8",
|
|
197
|
+
"EndpointID": "376d2c90a9e33a6e0fd62dc3f67c6f784d717594b54ebbb7e9d4d372ee0cf115",
|
|
198
|
+
"Gateway": "",
|
|
199
|
+
"IPAddress": "",
|
|
200
|
+
"IPPrefixLen": 0,
|
|
201
|
+
"IPv6Gateway": "",
|
|
202
|
+
"GlobalIPv6Address": "",
|
|
203
|
+
"GlobalIPv6PrefixLen": 0,
|
|
204
|
+
"MacAddress": "",
|
|
205
|
+
"DriverOpts": null
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
]
|
package/link-add.sh
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023, Viasat, Inc
|
|
4
|
+
# Licensed under MPL 2.0
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
usage () {
|
|
9
|
+
echo >&2 "${0} [OPTIONS] TYPE PID0 INTF0"
|
|
10
|
+
echo >&2 ""
|
|
11
|
+
echo >&2 "Create link TYPE interface INTF0 in netns PID0."
|
|
12
|
+
echo >&2 ""
|
|
13
|
+
echo >&2 "Positional arguments:"
|
|
14
|
+
echo >&2 " TYPE is the link/interface type"
|
|
15
|
+
echo >&2 " INTF0 is the primary interface name"
|
|
16
|
+
echo >&2 " PID0 is the primary netns process ID"
|
|
17
|
+
echo >&2 ""
|
|
18
|
+
echo >&2 "The INTF1/PID1 parameters have type specific meaning:"
|
|
19
|
+
echo >&2 " - veth: the peer interface in PID1 netns"
|
|
20
|
+
echo >&2 " - *vlan/*vtap: the parent interface in PID1 netns"
|
|
21
|
+
echo >&2 " - geneve/vxlan: not applicable"
|
|
22
|
+
echo >&2 ""
|
|
23
|
+
echo >&2 "OPTIONS:"
|
|
24
|
+
echo >&2 " --verbose - Verbose output (set -x)"
|
|
25
|
+
echo >&2 " --pid1 PID1 - Secondary netns process ID"
|
|
26
|
+
echo >&2 " (default: <SELF>)"
|
|
27
|
+
echo >&2 " --intf1 INTF1 - Secondary interface name"
|
|
28
|
+
echo >&2 " (default: eth0)"
|
|
29
|
+
echo >&2 " --ip IP0 - IP (CIDR) address for INTF0"
|
|
30
|
+
echo >&2 " --ip0 IP0 - IP (CIDR) address for INTF0"
|
|
31
|
+
echo >&2 " --ip1 IP1 - IP (CIDR) address for INTF1"
|
|
32
|
+
echo >&2 " --mac MAC0 - MAC address for INTF0"
|
|
33
|
+
echo >&2 " --mac0 MAC0 - MAC address for INTF0"
|
|
34
|
+
echo >&2 " --mac1 MAC1 - MAC address for INTF1"
|
|
35
|
+
echo >&2 " --route 'ROUTE' - route to add to INTF0"
|
|
36
|
+
echo >&2 " --route|--route0 'ROUTE' - route to add to INTF0"
|
|
37
|
+
echo >&2 " --route1 'ROUTE' - route to add to INTF1"
|
|
38
|
+
echo >&2 " --mtu MTU - MTU for both interfaces"
|
|
39
|
+
echo >&2 ""
|
|
40
|
+
echo >&2 " --mode MODE - Mode settings for *vlan TYPEs"
|
|
41
|
+
echo >&2 " --vlanid VLANID - VLAN ID for vlan TYPE"
|
|
42
|
+
echo >&2 ""
|
|
43
|
+
echo >&2 " --remote REMOTE - Remote address for geneve/vxlan types"
|
|
44
|
+
echo >&2 " --vni VNI - Virtual Network Identifier for geneve/vxlan types"
|
|
45
|
+
echo >&2 ""
|
|
46
|
+
echo >&2 " --netem NETEM - tc qdisc netem OPTIONS (man 8 netem)"
|
|
47
|
+
echo >&2 " --nat TARGET - Stateless NAT traffic to/from TARGET"
|
|
48
|
+
exit 2
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
info() { echo "link-add [${LOG_ID}] ${*}"; }
|
|
52
|
+
warn() { >&2 echo "link-add [${LOG_ID}] ${*}"; }
|
|
53
|
+
die() { warn "ERROR: ${*}"; exit 1; }
|
|
54
|
+
|
|
55
|
+
# Set MAC, IP, ROUTE, MTU, and up state for interface in netns
|
|
56
|
+
setup_if() {
|
|
57
|
+
local IF=$1 NS=$2 MAC=$3 IP=$4 ROUTE=$5 MTU=$6
|
|
58
|
+
|
|
59
|
+
info "Setting ${IP:+IP ${IP}, }${MAC:+MAC ${MAC}, }${MTU:+MTU ${MTU}, }${ROUTE:+ROUTE '${ROUTE}', }up state"
|
|
60
|
+
ip -netns ${NS} --force -b - <<EOF
|
|
61
|
+
${IP:+addr add ${IP} dev ${IF}}
|
|
62
|
+
${MAC:+link set dev ${IF} address ${MAC}}
|
|
63
|
+
${MTU:+link set dev ${IF} mtu ${MTU}}
|
|
64
|
+
link set dev ${IF} up
|
|
65
|
+
${ROUTE:+route add ${ROUTE} dev ${IF}}
|
|
66
|
+
EOF
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
IPTABLES() {
|
|
70
|
+
local ns=${1}; shift
|
|
71
|
+
ip netns exec ${ns} iptables -D "${@}" 2>/dev/null || true
|
|
72
|
+
ip netns exec ${ns} iptables -I "${@}"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Parse arguments
|
|
77
|
+
VERBOSE=${VERBOSE:-}
|
|
78
|
+
PID1=${PID1:-<SELF>} IF1=${IF1:-eth0}
|
|
79
|
+
IP0= IP1= MAC0= MAC1= ROUTE0= ROUTE1= MTU=
|
|
80
|
+
MODE= VLANID= REMOTE= VNI= NETEM= NAT=
|
|
81
|
+
positional=
|
|
82
|
+
while [ "${*}" ]; do
|
|
83
|
+
param=$1; OPTARG=$2
|
|
84
|
+
case ${param} in
|
|
85
|
+
--verbose) VERBOSE=1 ;;
|
|
86
|
+
--pid1) PID1="${OPTARG}"; shift ;;
|
|
87
|
+
--intf1) IF1="${OPTARG}"; shift ;;
|
|
88
|
+
--ip|--ip0) IP0="${OPTARG}"; shift ;;
|
|
89
|
+
--ip1) IP1="${OPTARG}"; shift ;;
|
|
90
|
+
--mac|--mac0) MAC0="${OPTARG}"; shift ;;
|
|
91
|
+
--mac1) MAC1="${OPTARG}"; shift ;;
|
|
92
|
+
--route|--route0) ROUTE0="${OPTARG}"; shift ;;
|
|
93
|
+
--route1) ROUTE1="${OPTARG}"; shift ;;
|
|
94
|
+
--mtu) MTU="${OPTARG}"; shift ;;
|
|
95
|
+
|
|
96
|
+
--mode) MODE="${OPTARG}"; shift ;;
|
|
97
|
+
--vlanid) VLANID="${OPTARG}"; shift ;;
|
|
98
|
+
|
|
99
|
+
--remote) REMOTE="${OPTARG}"; shift ;;
|
|
100
|
+
--vni) VNI="${OPTARG}"; shift ;;
|
|
101
|
+
|
|
102
|
+
--netem) NETEM="${OPTARG}"; shift ;;
|
|
103
|
+
--nat) NAT="${OPTARG}"; shift ;;
|
|
104
|
+
-h|--help) usage ;;
|
|
105
|
+
*) positional="${positional} $1" ;;
|
|
106
|
+
esac
|
|
107
|
+
shift
|
|
108
|
+
done
|
|
109
|
+
set -- ${positional}
|
|
110
|
+
TYPE=$1 PID0=$2 IF0=$3
|
|
111
|
+
|
|
112
|
+
[ "${VERBOSE}" ] && set -x || true
|
|
113
|
+
|
|
114
|
+
# Sanity check arguments
|
|
115
|
+
[ "${TYPE}" -a "${PID0}" -a "${IF0}" ] || usage
|
|
116
|
+
[ "${NAT}" -a -z "${IP0}" ] && die "--nat requires --ip0"
|
|
117
|
+
|
|
118
|
+
LOG_ID="${TYPE} ${PID0}:${IF0}"
|
|
119
|
+
case "${TYPE}" in
|
|
120
|
+
veth)
|
|
121
|
+
LOG_ID="${LOG_ID} <-> ${PID1}:${IF1}"
|
|
122
|
+
;;
|
|
123
|
+
*vlan|*vtap)
|
|
124
|
+
LOG_ID="${LOG_ID} <<< ${PID1}:${IF1}"
|
|
125
|
+
[ "${IF1}" ] || die "--intf1 required for ${TYPE} link"
|
|
126
|
+
[ "${REMOTE}" -o "${VNI}" ] && die "--remote/--vlanid incompatible with ${TYPE} link"
|
|
127
|
+
;;
|
|
128
|
+
geneve|vxlan)
|
|
129
|
+
LOG_ID="${LOG_ID} <<->> ${REMOTE}(${VNI})"
|
|
130
|
+
[ "${REMOTE}" -a "${VNI}" ] || die "--remote and --vni required for ${TYPE} link"
|
|
131
|
+
[ "${MODE}" -o "${VLANID}" ] && die "--mode/--vlanid incompatible with ${TYPE} link"
|
|
132
|
+
;;
|
|
133
|
+
*)
|
|
134
|
+
[ "${PID1}" != "<SELF>" ] && die "--pid1 not supported for ${TYPE} link"
|
|
135
|
+
;;
|
|
136
|
+
esac
|
|
137
|
+
|
|
138
|
+
[ "${PID1}" = "<SELF>" ] && PID1=$$
|
|
139
|
+
NS0=ns${PID0} NS1=ns${PID1}
|
|
140
|
+
|
|
141
|
+
# Sanity checks
|
|
142
|
+
[ ! -d /proc/$PID0 ] && die "PID0 $PID0 is no longer running!"
|
|
143
|
+
[ ! -d /proc/$PID1 ] && die "PID1 $PID1 is no longer running!"
|
|
144
|
+
|
|
145
|
+
### Do the work
|
|
146
|
+
|
|
147
|
+
info "Creating ${TYPE} link"
|
|
148
|
+
|
|
149
|
+
info "Creating ip netns to pid mappings"
|
|
150
|
+
export PATH=$PATH:/usr/sbin # to find iptables
|
|
151
|
+
mkdir -p /var/run/netns
|
|
152
|
+
ln -sf /proc/${PID0}/ns/net /var/run/netns/${NS0}
|
|
153
|
+
ln -sf /proc/${PID1}/ns/net /var/run/netns/${NS1}
|
|
154
|
+
|
|
155
|
+
case "${TYPE}" in
|
|
156
|
+
veth)
|
|
157
|
+
info "Creating ${TYPE} pair interfaces"
|
|
158
|
+
echo ip link add ${IF0} netns ${NS0} type veth peer ${IF1} netns ${NS1}
|
|
159
|
+
ip link add ${IF0} netns ${NS0} type veth peer ${IF1} netns ${NS1}
|
|
160
|
+
;;
|
|
161
|
+
*vlan|*vtap)
|
|
162
|
+
info "Creating ${TYPE} interface"
|
|
163
|
+
SIF0=if0-${RANDOM}
|
|
164
|
+
ip -netns ${NS1} link add name ${SIF0} link ${IF1} type ${TYPE} \
|
|
165
|
+
${MODE:+mode ${MODE}} ${VLANID:+id ${VLANID}}
|
|
166
|
+
info "Moving ${TYPE} interface"
|
|
167
|
+
ip -netns ${NS1} link set ${SIF0} netns ${NS0}
|
|
168
|
+
info "Renaming ${TYPE} interface"
|
|
169
|
+
ip -netns ${NS0} link set ${SIF0} name ${IF0}
|
|
170
|
+
;;
|
|
171
|
+
geneve|vxlan)
|
|
172
|
+
info "Creating ${TYPE} tunnel interface"
|
|
173
|
+
ip -netns ${NS1} link add name ${IF0} type ${TYPE} \
|
|
174
|
+
remote ${REMOTE} id ${VNI}
|
|
175
|
+
;;
|
|
176
|
+
*)
|
|
177
|
+
info "Creating ${TYPE} interface"
|
|
178
|
+
ip -netns ${NS0} link add ${IF0} type ${TYPE}
|
|
179
|
+
;;
|
|
180
|
+
esac
|
|
181
|
+
|
|
182
|
+
setup_if ${IF0} ${NS0} "${MAC0}" "${IP0}" "${ROUTE0}" "${MTU}"
|
|
183
|
+
[ "${TYPE}" = "veth" ] && \
|
|
184
|
+
setup_if ${IF1} ${NS1} "${MAC1}" "${IP1}" "${ROUTE1}" "${MTU}"
|
|
185
|
+
|
|
186
|
+
if [ "${NETEM}" ]; then
|
|
187
|
+
info "Setting tc qdisc netem: ${NETEM}"
|
|
188
|
+
tc -netns ${NS0} qdisc add dev ${IF0} root netem ${NETEM}
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
if [ "${NAT}" ]; then
|
|
192
|
+
info "Adding NAT rule to ${NAT}"
|
|
193
|
+
IPTABLES ${NS0} PREROUTING -t nat -i ${IF0} -j DNAT --to-destination ${NAT}
|
|
194
|
+
IPTABLES ${NS0} POSTROUTING -t nat -o ${IF0} -j SNAT --to-source ${IP0%/*}
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
info "Created ${TYPE} link"
|
package/link-del.sh
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023, Viasat, Inc
|
|
4
|
+
# Licensed under MPL 2.0
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
usage () {
|
|
9
|
+
echo >&2 "${0} [OPTIONS] PID INTF"
|
|
10
|
+
echo >&2 ""
|
|
11
|
+
echo >&2 " INTF is the name of the interface in PID netns"
|
|
12
|
+
echo >&2 " PID is the process ID of the container"
|
|
13
|
+
echo >&2 ""
|
|
14
|
+
echo >&2 " Where OPTIONS are:"
|
|
15
|
+
echo >&2 " --verbose - Verbose output (set -x)"
|
|
16
|
+
exit 2
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
VERBOSE=${VERBOSE:-}
|
|
20
|
+
|
|
21
|
+
info() { echo "del-link [${PID}:${IF}] ${*}"; }
|
|
22
|
+
warn() { >&2 echo "del-link [${PID}:${IF}] ${*}"; }
|
|
23
|
+
die() { warn "ERROR: ${*}"; exit 1; }
|
|
24
|
+
|
|
25
|
+
# Parse arguments
|
|
26
|
+
positional=
|
|
27
|
+
while [ "${*}" ]; do
|
|
28
|
+
param=$1; OPTARG=$2
|
|
29
|
+
case ${param} in
|
|
30
|
+
--verbose) VERBOSE=1 ;;
|
|
31
|
+
-h|--help) usage ;;
|
|
32
|
+
*) positional="${positional} $1" ;;
|
|
33
|
+
esac
|
|
34
|
+
shift
|
|
35
|
+
done
|
|
36
|
+
set -- ${positional}
|
|
37
|
+
PID=$1 IF=$2
|
|
38
|
+
|
|
39
|
+
NS=ns${PID}
|
|
40
|
+
|
|
41
|
+
[ "${VERBOSE}" ] && set -x || true
|
|
42
|
+
|
|
43
|
+
# Check arguments
|
|
44
|
+
[ "${IF}" -a "${PID}" ] || usage
|
|
45
|
+
|
|
46
|
+
# Sanity checks
|
|
47
|
+
[ ! -d /proc/$PID ] && die "PID $PID is no longer running!"
|
|
48
|
+
|
|
49
|
+
### Do the work
|
|
50
|
+
|
|
51
|
+
info "Deleting link"
|
|
52
|
+
|
|
53
|
+
info "Creating ip netns to pid mapping"
|
|
54
|
+
mkdir -p /var/run/netns
|
|
55
|
+
ln -sf /proc/${PID}/ns/net /var/run/netns/ns${PID}
|
|
56
|
+
|
|
57
|
+
info "Deleting interface"
|
|
58
|
+
ip -netns ${NS} link del ${IF}
|
|
59
|
+
|
|
60
|
+
info "Deleted link"
|
package/net2dot
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
TOP_DIR=$(dirname $(readlink -f "${0}"))
|
|
4
|
+
SCRIPT_NAME=$(basename "${0}")
|
|
5
|
+
NBB=${TOP_DIR}/node_modules/.bin/nbb
|
|
6
|
+
|
|
7
|
+
die() { echo >&2 "${*}"; exit 1; }
|
|
8
|
+
|
|
9
|
+
[ -e "${NBB}" ] || die "Missing ${NBB}. Maybe run 'npm install' in ${TOP_DIR}?"
|
|
10
|
+
|
|
11
|
+
exec ${NBB} -cp "${TOP_DIR}/src" -m conlink.net2dot/main "${@}"
|
package/notes.txt
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
- Also see schema-ish.yaml
|
|
2
|
+
links:
|
|
3
|
+
- type: TYPE # Default: 'veth'
|
|
4
|
+
# Others: '*vlan/*vtap', 'dummy', 'tunnel', etc
|
|
5
|
+
|
|
6
|
+
container: FOO # full container name
|
|
7
|
+
# OR
|
|
8
|
+
service: FOO # compose service name
|
|
9
|
+
|
|
10
|
+
bridge: BRIDGE # name of OVS or linux bridge
|
|
11
|
+
|
|
12
|
+
base: BASE # 'conlink', 'host', or 'local'
|
|
13
|
+
# 'conlink' is default for 'type: veth'
|
|
14
|
+
# 'host' is default for 'type: *vlan/*vtap'
|
|
15
|
+
|
|
16
|
+
dev: DEV # internal container device/interface name
|
|
17
|
+
outer-dev: DEV # conlink or host (*vlan) device/interface name
|
|
18
|
+
|
|
19
|
+
# --- optional general ---
|
|
20
|
+
|
|
21
|
+
ip(s): IP # starting address, can include net slash to limit max
|
|
22
|
+
mac: MAC
|
|
23
|
+
mtu: MTU
|
|
24
|
+
route(s): ROUTE # `ip route add ROUTE`, maybe add "dev INTF" automatically
|
|
25
|
+
tc(s): TC # tc/qdisc commands/settings
|
|
26
|
+
flow(s): FLOW # `ovs-ofctl add-flow DOMAIN FLOW`. With var templating.
|
|
27
|
+
command(s): CMD # arbitrary shell cmd. After all links setup for this container
|
|
28
|
+
|
|
29
|
+
# --- optional for 'type: *vlan/*vtap' ---
|
|
30
|
+
|
|
31
|
+
mode: MODE # 'bridge', etc
|
|
32
|
+
vlanid: VLANID # VLAN #
|
|
33
|
+
nat: NAT # nat target
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
- type maps to 'ip link' type with default of 'veth'
|
|
37
|
+
- when type is 'veth', then base default is 'conlink'
|
|
38
|
+
- when type is 'veth' and base is 'conlink', then bridge is required.
|
|
39
|
+
|
|
40
|
+
- conlink veth link: {type: veth [DEFAULT], base: conlink [DEFAULT], bridge: BRIDGE, dev: DEV}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
Dependencies in python version:
|
|
45
|
+
- argparse
|
|
46
|
+
- shlex (parsing commands)
|
|
47
|
+
- compose_interpolation import TemplateWithDefaults
|
|
48
|
+
- cerberus import Validator
|
|
49
|
+
- options: joi, ajv, json-schema, and z-schema.
|
|
50
|
+
- docker
|
|
51
|
+
- psutil (pid_exists)
|
|
52
|
+
- json
|
|
53
|
+
- yaml
|
|
54
|
+
- mininet
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
- [deprecated idea] conlink sub-commands:
|
|
58
|
+
conlink spit
|
|
59
|
+
- output override docker-compose file with conlink service
|
|
60
|
+
- figure out volume mounts to get to other compose file(s)
|
|
61
|
+
conlink dc up ...
|
|
62
|
+
- generate override docker-compose file with conlink service
|
|
63
|
+
- run the compose command with override file
|
|
64
|
+
conlink start
|
|
65
|
+
- start inside compose
|
|
66
|
+
conlink run
|
|
67
|
+
- start outside compose
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
tc:
|
|
71
|
+
tc-htb:
|
|
72
|
+
- replace cbq, control outbound bandwidth
|
|
73
|
+
tc qdisc ... dev dev ( parent classid | root) [ handle major: ] htb [ default minor-id ]
|
|
74
|
+
tc class ... dev dev parent major:[minor] [ classid major:minor ] htb rate rate [ ceil rate ] burst bytes [ cburst bytes ] [ prio priority ]
|
|
75
|
+
|
|
76
|
+
tc-cbq:
|
|
77
|
+
tc qdisc ... dev dev ( parent classid | root) [ handle major: ] cbq [ allot bytes ] avpkt bytes bandwidth rate [ cell bytes ] [ ewma log ] [ mpu bytes ]
|
|
78
|
+
tc class ... dev dev parent major:[minor] [ classid major:minor ] cbq allot bytes [ bandwidth rate ] [ rate rate ] prio pri‐ority [ weight weight ] [ minburst packets ] [ maxburst packets ] [ ewma log ] [ cell bytes ] avpkt bytes [ mpu bytes ] [ bounded isolated ] [ split handle & defmap defmap ] [ estimator interval timeconstant ]
|
|
79
|
+
|
|
80
|
+
tc-netem:
|
|
81
|
+
tc qdisc ... dev DEVICE ] add netem OPTIONS
|
|
82
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
FROM node:16 as base
|
|
2
|
+
|
|
3
|
+
RUN apt-get -y update #1
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
#############################################################
|
|
7
|
+
FROM node:16-slim as conlink
|
|
8
|
+
|
|
9
|
+
RUN apt-get -y update #1
|
|
10
|
+
|
|
11
|
+
# network/debug
|
|
12
|
+
RUN apt-get -y install util-linux iproute2 bridge-utils tzdata \
|
|
13
|
+
iptables ethtool tcpdump socat iputils-ping strace socat \
|
|
14
|
+
curl wget iperf3 dnsmasq jq psutils telnet
|
|
15
|
+
|
|
16
|
+
# runtime deps
|
|
17
|
+
RUN apt-get -y install net-tools cgroup-tools \
|
|
18
|
+
openvswitch-switch openvswitch-testcontroller kmod
|
|
19
|
+
|
|
20
|
+
ADD package.json /app/
|
|
21
|
+
RUN cd /app && npm install
|
|
22
|
+
|
|
23
|
+
ADD conlink conlink.cljs /app/
|
|
24
|
+
ADD src/ /app/src/
|
|
25
|
+
RUN ln -sf /app/conlink /sbin/
|
|
26
|
+
|
package/old/add-link.sh
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2023, Viasat, Inc
|
|
4
|
+
# Licensed under MPL 2.0
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
usage () {
|
|
9
|
+
echo >&2 "${0} [OPTIONS] TYPE INTF PID [-- SET ARGS]"
|
|
10
|
+
echo >&2 ""
|
|
11
|
+
echo >&2 " TYPE: interface type"
|
|
12
|
+
echo >&2 " INTF: the interface name to create in PID"
|
|
13
|
+
echo >&2 " PID: the process ID of the first namespace"
|
|
14
|
+
echo >&2 ""
|
|
15
|
+
echo >&2 " OPTIONS are:"
|
|
16
|
+
echo >&2 " --verbose - Verbose output (set -x)"
|
|
17
|
+
echo >&2 " --ip IP - IP address for INTF"
|
|
18
|
+
echo >&2 " --mac MAC - MAC address for INTF"
|
|
19
|
+
echo >&2 " --route 'ROUTE' - route to add to INTF"
|
|
20
|
+
echo >&2 " --mtu MTU - MTU for INTF"
|
|
21
|
+
echo >&2 ""
|
|
22
|
+
echo >&2 "The interface is created in PID ns, then the IP, MAC,"
|
|
23
|
+
echo >&2 "and MTU are set, and finally the following command"
|
|
24
|
+
echo >&2 "is executed:"
|
|
25
|
+
echo >&2 " ip link set INTF up SET_ARGS"
|
|
26
|
+
exit 2
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
VERBOSE=${VERBOSE:-}
|
|
30
|
+
IP= MAC= ROUTE= MTU= SET_ARGS=
|
|
31
|
+
|
|
32
|
+
info() { echo "add-link [${TYPE} - ${PID}/${IF}] ${*}"; }
|
|
33
|
+
warn() { >&2 echo "add-link [${TYPE} - ${PID}/${IF}] ${*}"; }
|
|
34
|
+
die() { warn "ERROR: ${*}"; exit 1; }
|
|
35
|
+
|
|
36
|
+
# Parse arguments
|
|
37
|
+
positional=
|
|
38
|
+
while [ "${*}" ]; do
|
|
39
|
+
param=$1; OPTARG=$2
|
|
40
|
+
case ${param} in
|
|
41
|
+
--verbose) VERBOSE=1 ;;
|
|
42
|
+
--ip) IP="${OPTARG}"; shift ;;
|
|
43
|
+
--mac) MAC="${OPTARG}"; shift ;;
|
|
44
|
+
--route) ROUTE="${OPTARG}"; shift ;;
|
|
45
|
+
--mtu) MTU="${OPTARG}"; shift ;;
|
|
46
|
+
-h|--help) usage ;;
|
|
47
|
+
--) SET_ARGS="$*"; break ;;
|
|
48
|
+
*) positional="${positional} $1" ;;
|
|
49
|
+
esac
|
|
50
|
+
shift
|
|
51
|
+
done
|
|
52
|
+
set -- ${positional}
|
|
53
|
+
|
|
54
|
+
TYPE=$1 IF=$2 PID=$3 NS=ns${PID}
|
|
55
|
+
|
|
56
|
+
[ "${VERBOSE}" ] && set -x || true
|
|
57
|
+
|
|
58
|
+
# Check arguments
|
|
59
|
+
[ "${TYPE}" -a "${IF}" -a "${PID}" ] || usage
|
|
60
|
+
|
|
61
|
+
# Sanity checks
|
|
62
|
+
[ ! -d /proc/$PID ] && die "PID $PID is no longer running!"
|
|
63
|
+
|
|
64
|
+
export PATH=$PATH:/usr/sbin
|
|
65
|
+
mkdir -p /var/run/netns
|
|
66
|
+
ln -sf /proc/${PID}/ns/net /var/run/netns/${NS}
|
|
67
|
+
|
|
68
|
+
info "Creating ${TYPE} link ${IF} in ${NS}"
|
|
69
|
+
ip link add ${IF} netns ns${PID} type ${TYPE}
|
|
70
|
+
|
|
71
|
+
ip -netns ${NS} --force -b - <<EOF
|
|
72
|
+
${IP:+addr add ${IP} dev ${IF}}
|
|
73
|
+
${MAC:+link set dev ${IF} address ${MAC}}
|
|
74
|
+
${MTU:+link set dev ${IF} mtu ${MTU}}
|
|
75
|
+
link set dev ${IF} up
|
|
76
|
+
${ROUTE:+route add ${ROUTE} dev ${IF}}
|
|
77
|
+
${SET_ARGS:+link set dev ${IF} ${SET_ARGS}}
|
|
78
|
+
EOF
|
|
79
|
+
|
|
80
|
+
info "Created ${TYPE} link ${IF} in ${NS}"
|
|
81
|
+
|
|
82
|
+
# /test/add-link.sh --verbose dummy if0 2500144 --ip 192.168.88.32/24 -- arp on
|
package/old/conlink
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
TOP_DIR=$(dirname $(readlink -f "${0}"))
|
|
4
|
+
SCRIPT_NAME=$(basename "${0}")
|
|
5
|
+
NBB=${TOP_DIR}/node_modules/.bin/nbb
|
|
6
|
+
|
|
7
|
+
die() { echo >&2 "${*}"; exit 1; }
|
|
8
|
+
|
|
9
|
+
[ -e "${NBB}" ] || die "Missing ${NBB}. Maybe run 'npm install' in ${TOP_DIR}?"
|
|
10
|
+
|
|
11
|
+
exec ${NBB} -cp "${TOP_DIR}/src" "${TOP_DIR}"/${SCRIPT_NAME}.cljs "${@}"
|
|
12
|
+
|