netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / utilities / ovs-docker
1 #!/bin/bash
2 # Copyright (C) 2014 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 # Check for programs we'll need.
17 search_path () {
18     save_IFS=$IFS
19     IFS=:
20     for dir in $PATH; do
21         IFS=$save_IFS
22         if test -x "$dir/$1"; then
23             return 0
24         fi
25     done
26     IFS=$save_IFS
27     echo >&2 "$0: $1 not found in \$PATH, please install and try again"
28     exit 1
29 }
30
31 ovs_vsctl () {
32     ovs-vsctl --timeout=60 "$@"
33 }
34
35 create_netns_link () {
36     mkdir -p /var/run/netns
37     if [ ! -e /var/run/netns/"$PID" ]; then
38         ln -s /proc/"$PID"/ns/net /var/run/netns/"$PID"
39         trap 'delete_netns_link' 0
40         for signal in 1 2 3 13 14 15; do
41             trap 'delete_netns_link; trap - $signal; kill -$signal $$' $signal
42         done
43     fi
44 }
45
46 delete_netns_link () {
47     rm -f /var/run/netns/"$PID"
48 }
49
50 get_port_for_container_interface () {
51     CONTAINER="$1"
52     INTERFACE="$2"
53
54     PORT=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
55              external_ids:container_id="$CONTAINER"  \
56              external_ids:container_iface="$INTERFACE"`
57     if [ -z "$PORT" ]; then
58         echo >&2 "$UTIL: Failed to find any attached port" \
59                  "for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"
60     fi
61     echo "$PORT"
62 }
63
64 add_port () {
65     BRIDGE="$1"
66     INTERFACE="$2"
67     CONTAINER="$3"
68
69     if [ -z "$BRIDGE" ] || [ -z "$INTERFACE" ] || [ -z "$CONTAINER" ]; then
70         echo >&2 "$UTIL add-port: not enough arguments (use --help for help)"
71         exit 1
72     fi
73
74     shift 3
75     while [ $# -ne 0 ]; do
76         case $1 in
77             --ipaddress=*)
78                 ADDRESS=`expr X"$1" : 'X[^=]*=\(.*\)'`
79                 shift
80                 ;;
81             --macaddress=*)
82                 MACADDRESS=`expr X"$1" : 'X[^=]*=\(.*\)'`
83                 shift
84                 ;;
85             --gateway=*)
86                 GATEWAY=`expr X"$1" : 'X[^=]*=\(.*\)'`
87                 shift
88                 ;;
89             --mtu=*)
90                 MTU=`expr X"$1" : 'X[^=]*=\(.*\)'`
91                 shift
92                 ;;
93             *)
94                 echo >&2 "$UTIL add-port: unknown option \"$1\""
95                 exit 1
96                 ;;
97         esac
98     done
99
100     # Check if a port is already attached for the given container and interface
101     PORT=`get_port_for_container_interface "$CONTAINER" "$INTERFACE" \
102             2>/dev/null`
103     if [ -n "$PORT" ]; then
104         echo >&2 "$UTIL: Port already attached" \
105                  "for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"
106         exit 1
107     fi
108
109     if ovs_vsctl br-exists "$BRIDGE" || \
110         ovs_vsctl add-br "$BRIDGE"; then :; else
111         echo >&2 "$UTIL: Failed to create bridge $BRIDGE"
112         exit 1
113     fi
114
115     if PID=`docker inspect -f '{{.State.Pid}}' "$CONTAINER"`; then :; else
116         echo >&2 "$UTIL: Failed to get the PID of the container"
117         exit 1
118     fi
119
120     create_netns_link
121
122     # Create a veth pair.
123     ID=`uuidgen | sed 's/-//g'`
124     PORTNAME="${ID:0:13}"
125     ip link add "${PORTNAME}_l" type veth peer name "${PORTNAME}_c"
126
127     # Add one end of veth to OVS bridge.
128     if ovs_vsctl --may-exist add-port "$BRIDGE" "${PORTNAME}_l" \
129        -- set interface "${PORTNAME}_l" \
130        external_ids:container_id="$CONTAINER" \
131        external_ids:container_iface="$INTERFACE"; then :; else
132         echo >&2 "$UTIL: Failed to add "${PORTNAME}_l" port to bridge $BRIDGE"
133         ip link delete "${PORTNAME}_l"
134         exit 1
135     fi
136
137     ip link set "${PORTNAME}_l" up
138
139     # Move "${PORTNAME}_c" inside the container and changes its name.
140     ip link set "${PORTNAME}_c" netns "$PID"
141     ip netns exec "$PID" ip link set dev "${PORTNAME}_c" name "$INTERFACE"
142     ip netns exec "$PID" ip link set "$INTERFACE" up
143
144     if [ -n "$MTU" ]; then
145         ip netns exec "$PID" ip link set dev "$INTERFACE" mtu "$MTU"
146     fi
147
148     if [ -n "$ADDRESS" ]; then
149         ip netns exec "$PID" ip addr add "$ADDRESS" dev "$INTERFACE"
150     fi
151
152     if [ -n "$MACADDRESS" ]; then
153         ip netns exec "$PID" ip link set dev "$INTERFACE" address "$MACADDRESS"
154     fi
155
156     if [ -n "$GATEWAY" ]; then
157         ip netns exec "$PID" ip route add default via "$GATEWAY"
158     fi
159 }
160
161 del_port () {
162     BRIDGE="$1"
163     INTERFACE="$2"
164     CONTAINER="$3"
165
166     if [ "$#" -lt 3 ]; then
167         usage
168         exit 1
169     fi
170
171     PORT=`get_port_for_container_interface "$CONTAINER" "$INTERFACE"`
172     if [ -z "$PORT" ]; then
173         exit 1
174     fi
175
176     ovs_vsctl --if-exists del-port "$PORT"
177
178     ip link delete "$PORT"
179 }
180
181 del_ports () {
182     BRIDGE="$1"
183     CONTAINER="$2"
184     if [ "$#" -lt 2 ]; then
185         usage
186         exit 1
187     fi
188
189     PORTS=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
190              external_ids:container_id="$CONTAINER"`
191     if [ -z "$PORTS" ]; then
192         exit 0
193     fi
194
195     for PORT in $PORTS; do
196         ovs_vsctl --if-exists del-port "$PORT"
197         ip link delete "$PORT"
198     done
199 }
200
201 set_vlan () {
202     BRIDGE="$1"
203     INTERFACE="$2"
204     CONTAINER_ID="$3"
205     VLAN="$4"
206
207     if [ "$#" -lt 4 ]; then
208         usage
209         exit 1
210     fi
211
212     PORT=`get_port_for_container_interface "$CONTAINER_ID" "$INTERFACE"`
213     if [ -z "$PORT" ]; then
214         exit 1
215     fi
216     ovs_vsctl set port "$PORT" tag="$VLAN"
217 }
218
219 usage() {
220     cat << EOF
221 ${UTIL}: Performs integration of Open vSwitch with Docker.
222 usage: ${UTIL} COMMAND
223
224 Commands:
225   add-port BRIDGE INTERFACE CONTAINER [--ipaddress="ADDRESS"]
226                     [--gateway=GATEWAY] [--macaddress="MACADDRESS"]
227                     [--mtu=MTU]
228                     Adds INTERFACE inside CONTAINER and connects it as a port
229                     in Open vSwitch BRIDGE. Optionally, sets ADDRESS on
230                     INTERFACE. ADDRESS can include a '/' to represent network
231                     prefix length. Optionally, sets a GATEWAY, MACADDRESS
232                     and MTU.  e.g.:
233                     ${UTIL} add-port br-int eth1 c474a0e2830e
234                     --ipaddress=192.168.1.2/24 --gateway=192.168.1.1
235                     --macaddress="a2:c3:0d:49:7f:f8" --mtu=1450
236   del-port BRIDGE INTERFACE CONTAINER
237                     Deletes INTERFACE inside CONTAINER and removes its
238                     connection to Open vSwitch BRIDGE. e.g.:
239                     ${UTIL} del-port br-int eth1 c474a0e2830e
240   del-ports BRIDGE CONTAINER
241                     Removes all Open vSwitch interfaces from CONTAINER. e.g.:
242                     ${UTIL} del-ports br-int c474a0e2830e
243   set-vlan BRIDGE INTERFACE CONTAINER VLAN
244                     Configures the INTERFACE of CONTAINER attached to BRIDGE
245                     to become an access port of VLAN. e.g.:
246                     ${UTIL} set-vlan br-int eth1 c474a0e2830e 5
247 Options:
248   -h, --help        display this help message.
249 EOF
250 }
251
252 UTIL=$(basename $0)
253 search_path ovs-vsctl
254 search_path docker
255 search_path uuidgen
256
257 if (ip netns) > /dev/null 2>&1; then :; else
258     echo >&2 "$UTIL: ip utility not found (or it does not support netns),"\
259              "cannot proceed"
260     exit 1
261 fi
262
263 if [ $# -eq 0 ]; then
264     usage
265     exit 0
266 fi
267
268 case $1 in
269     "add-port")
270         shift
271         add_port "$@"
272         exit 0
273         ;;
274     "del-port")
275         shift
276         del_port "$@"
277         exit 0
278         ;;
279     "del-ports")
280         shift
281         del_ports "$@"
282         exit 0
283         ;;
284     "set-vlan")
285         shift
286         set_vlan "$@"
287         exit 0
288         ;;
289     -h | --help)
290         usage
291         exit 0
292         ;;
293     *)
294         echo >&2 "$UTIL: unknown command \"$1\" (use --help for help)"
295         exit 1
296         ;;
297 esac