Skip to content

Commit 751bfac

Browse files
committed
add netns flag to taskworkflow example.
The '-netns' flag lets callers specify a network namespace for firecracker VM process. Signed-off-by: Anirudh Aithal <[email protected]>
1 parent 76df937 commit 751bfac

File tree

2 files changed

+103
-21
lines changed

2 files changed

+103
-21
lines changed

examples/taskworkflow.go

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,41 @@ import (
3333
)
3434

3535
const (
36-
kernelArgsFormat = "console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw ip=%s::%s:%s:::off::::"
37-
macAddress = "AA:FC:00:00:00:01"
38-
hostDevName = "tap0"
36+
kernelArgsFormat = "console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw ip=%s::%s:%s:::off::::"
37+
defaultMacAddress = "AA:FC:00:00:00:01"
38+
defaultHostDevName = "tap0"
3939
)
4040

4141
func main() {
4242
var ip = flag.String("ip", "", "ip address assigned to the container. Example: -ip 172.16.0.1")
4343
var gateway = flag.String("gw", "", "gateway ip address. Example: -gw 172.16.0.1")
4444
var netMask = flag.String("mask", "", "subnet gatway mask. Example: -mask 255.255.255.0")
45+
var netNS = flag.String("netns", "", "firecracker VM network namespace. Example: -netNS testing")
46+
var hostDevName = flag.String("host_device", defaultHostDevName,
47+
"the host device name for the network interface, required when specifying 'netns'. Example: -host_device tap0")
48+
var macAddress = flag.String("mac", defaultMacAddress,
49+
"the mac address for the network interface, required when specifying 'netns'. Example: -mac AA:FC:00:00:00:01")
50+
var kernelNetworkArgs = flag.Bool("kernel_nw_args", false,
51+
"specifies if network params for the VMs should be included with kernel args. Example: -kernel_nw_args true")
4552
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
4653
flag.Parse()
47-
if *ip != "" && (*gateway == "" || *netMask == "") {
48-
log.Fatal("Incorrect usage. 'gw' and 'mask' need to be specified when 'ip' is specified")
54+
if *kernelNetworkArgs && (*gateway == "" || *netMask == "") {
55+
log.Fatal("Incorrect usage. 'gw' and 'mask' need to be specified when 'kernel_nw_args' is set")
4956
}
50-
if err := taskWorkflow(*ip, *gateway, *netMask); err != nil {
57+
if err := taskWorkflow(*ip, *kernelNetworkArgs, *gateway, *netMask, *macAddress, *hostDevName, *netNS); err != nil {
5158
log.Fatal(err)
5259
}
5360
}
5461

55-
func taskWorkflow(containerIP string, gateway string, netMask string) error {
62+
func taskWorkflow(
63+
containerIP string,
64+
kernelNetworkArgs bool,
65+
gateway string,
66+
netMask string,
67+
macAddress string,
68+
hostDevName string,
69+
netNS string,
70+
) error {
5671
log.Println("Creating containerd client")
5772
client, err := containerd.New("/run/containerd/containerd.sock")
5873
if err != nil {
@@ -93,21 +108,23 @@ func taskWorkflow(containerIP string, gateway string, netMask string) error {
93108
task, err := container.NewTask(ctx,
94109
cio.NewCreator(cio.WithStdio),
95110
func(ctx context.Context, _ *containerd.Client, ti *containerd.TaskInfo) error {
96-
if containerIP == "" {
111+
if containerIP == "" && netNS == "" {
112+
// No params to configure, return.
97113
return nil
98114
}
99-
// An IP address for the container has been provided. Configure
100-
// the VM opts accordingly.
101-
firecrackerConfig := &proto.FirecrackerConfig{
102-
NetworkInterfaces: []*proto.FirecrackerNetworkInterface{
103-
{
104-
MacAddress: macAddress,
105-
HostDevName: hostDevName,
106-
},
107-
},
108-
KernelArgs: fmt.Sprintf(kernelArgsFormat, containerIP, gateway, netMask),
115+
// An IP address or the network namespace for the container has
116+
// been provided. Configure VM opts accordingly.
117+
builder := newFirecrackerConfigBuilder()
118+
if containerIP != "" {
119+
builder.setNetworkConfig(macAddress, hostDevName)
109120
}
110-
ti.Options = firecrackerConfig
121+
if kernelNetworkArgs {
122+
builder.setKernelNetworkArgs(containerIP, gateway, netMask)
123+
}
124+
if netNS != "" {
125+
builder.setNetNS(netNS)
126+
}
127+
ti.Options = builder.build()
111128
return nil
112129
})
113130
if err != nil {
@@ -151,6 +168,47 @@ func taskWorkflow(containerIP string, gateway string, netMask string) error {
151168
return nil
152169
}
153170

171+
type firecrackerConfigBuilder struct {
172+
vmConfig *proto.FirecrackerConfig
173+
}
174+
175+
func newFirecrackerConfigBuilder() *firecrackerConfigBuilder {
176+
return &firecrackerConfigBuilder{
177+
vmConfig: &proto.FirecrackerConfig{},
178+
}
179+
}
180+
181+
func (builder *firecrackerConfigBuilder) build() *proto.FirecrackerConfig {
182+
return builder.vmConfig
183+
}
184+
185+
// setNetworkConfig sets the fields in the protobuf message required to
186+
// configure the VM with the container IP, gateway and netmask sepcified.
187+
func (builder *firecrackerConfigBuilder) setNetworkConfig(
188+
macAddress string,
189+
hostDevName string,
190+
) {
191+
builder.vmConfig.NetworkInterfaces = []*proto.FirecrackerNetworkInterface{
192+
{
193+
MacAddress: macAddress,
194+
HostDevName: hostDevName,
195+
},
196+
}
197+
}
198+
199+
func (builder *firecrackerConfigBuilder) setKernelNetworkArgs(
200+
containerIP string,
201+
gateway string,
202+
netMask string,
203+
) {
204+
builder.vmConfig.KernelArgs = fmt.Sprintf(kernelArgsFormat, containerIP, gateway, netMask)
205+
}
206+
207+
// setNetNS sets the network namespace field in the protobuf message.
208+
func (builder *firecrackerConfigBuilder) setNetNS(netNS string) {
209+
builder.vmConfig.FirecrackerNetworkNamespace = netNS
210+
}
211+
154212
func getResponse(containerIP string) {
155213
response, err := http.Get("http://" + containerIP)
156214
if err != nil {

examples/taskworkflow.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,29 @@ After checking out the `firecracker-containerd` repo, you can build this
88
example using the `make examples` command.
99

1010
### Running
11+
12+
#### Basic workflow (no networking)
1113
For a basic workflow, without any networking setup, just run the executable
1214
built with the command in the previous section as super user:
1315
```bash
1416
$ sudo /path/to/firecracker-containerd/examples/taskworkflow
1517
```
1618

19+
#### Workflow to create container, with networking
1720
For a workflow with networking setup for the container, create a tap device
1821
for the VM by following [these instructions](https://github.com/firecracker-microvm/firecracker/blob/master/docs/network-setup.md).
1922

2023
This creates a tap device named `tap0`, in the local `172.16.0.1/24` subnet.
2124
Since the example does not rely on a DHCP client running within the VM to
2225
initialize the network interface, `gw` and `mask` flags should be used to
23-
specify the gateway and subnet mask values.
26+
specify the gateway and subnet mask values, along with the `kernel_nw_args`
27+
flag.
2428

2529
The following example sets:
2630
* The IP address to `172.16.0.2`
2731
* The gateway IP address to `172.16.0.1`
2832
* The subnet mask to `255.255.255.0` (`/24`)
33+
* Kernel args to specify all 3 of these
2934

3035
** NOTE: This example will not work if you're running more than 1 container
3136
on a host at the same time **
@@ -34,7 +39,8 @@ Now, run the example by passing the `-ip` argument:
3439
```bash
3540
$ sudo /path/to/firecracker-containerd/examples/taskworkflow -ip 172.16.0.2 \
3641
-gw 172.16.0.1 \
37-
-mask 255.255.255.0
42+
-mask 255.255.255.0 \
43+
-kernel_nw_args
3844
```
3945

4046
You should see output similar to this:
@@ -75,3 +81,21 @@ Commercial support is available at
7581
]
7682
172.16.0.1 - - [11/Feb/2019:21:02:54 +0000] "GET / HTTP/1.1" 200 612 "-" "Go-http-client/1.1" "-"
7783
```
84+
85+
#### Workflow to create container, with firecracker process in a netns
86+
For a workflow with networking setup for a container, where network parameters
87+
are being dervied from a network namespace, the `-netns` argument can be
88+
used.
89+
90+
```bash
91+
sudo /path/to/firecracker-containerd/examples/taskworkflow -ip 10.0.5.33 \
92+
-host_device tap301 \
93+
-mac aa:bb:cc:dd:ee:ff \
94+
-netns vlan301
95+
```
96+
97+
The above example command assumes that a vlan device with vlan tag `301` has
98+
been setup with the `tap301` tap device in the `vlan301` network namespace.
99+
Since `-kernel_nw_args` has not been set, it's also assumed that the rootfs
100+
image for the VM has a DHCP client that runs on boot. The ip address for the
101+
vlan device is assumed to be `10.0.5.33` as well.

0 commit comments

Comments
 (0)