Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
6f6bd412
Unverified
Commit
6f6bd412
authored
Jan 10, 2020
by
Stéphane Graber
Committed by
GitHub
Jan 10, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3248 from brauner/2020-01-05/veth_devices
network: improve veth device creation
parents
90ddf3c0
8bf64b77
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
248 additions
and
207 deletions
+248
-207
lxc_user_nic.c
src/lxc/cmd/lxc_user_nic.c
+10
-21
network.c
src/lxc/network.c
+189
-183
network.h
src/lxc/network.h
+2
-1
api_reboot.c
src/tests/api_reboot.c
+47
-2
No files found.
src/lxc/cmd/lxc_user_nic.c
View file @
6f6bd412
...
...
@@ -487,11 +487,11 @@ static char *find_line(char *buf_start, char *buf_end, char *name,
return
NULL
;
}
static
int
instantiate_veth
(
char
*
veth1
,
char
*
veth2
)
static
int
instantiate_veth
(
char
*
veth1
,
char
*
veth2
,
pid_t
pid
,
unsigned
int
mtu
)
{
int
ret
;
ret
=
lxc_veth_create
(
veth1
,
veth2
);
ret
=
lxc_veth_create
(
veth1
,
veth2
,
pid
,
mtu
);
if
(
ret
<
0
)
{
errno
=
-
ret
;
CMD_SYSERROR
(
"Failed to create %s-%s
\n
"
,
veth1
,
veth2
);
...
...
@@ -524,8 +524,9 @@ static int get_mtu(char *name)
static
int
create_nic
(
char
*
nic
,
char
*
br
,
int
pid
,
char
**
cnic
)
{
unsigned
int
mtu
=
1500
;
int
ret
;
char
veth1buf
[
IFNAMSIZ
],
veth2buf
[
IFNAMSIZ
];
int
mtu
,
ret
;
ret
=
snprintf
(
veth1buf
,
IFNAMSIZ
,
"%s"
,
nic
);
if
(
ret
<
0
||
ret
>=
IFNAMSIZ
)
{
...
...
@@ -539,16 +540,19 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
return
-
1
;
}
if
(
strcmp
(
br
,
"none"
))
mtu
=
get_mtu
(
br
);
if
(
!
mtu
)
mtu
=
1500
;
/* create the nics */
ret
=
instantiate_veth
(
veth1buf
,
veth2buf
);
ret
=
instantiate_veth
(
veth1buf
,
veth2buf
,
pid
,
mtu
);
if
(
ret
<
0
)
{
usernic_error
(
"%s"
,
"Error creating veth tunnel
\n
"
);
return
-
1
;
}
if
(
strcmp
(
br
,
"none"
))
{
/* copy the bridge's mtu to both ends */
mtu
=
get_mtu
(
br
);
if
(
mtu
>
0
)
{
ret
=
lxc_netdev_set_mtu
(
veth1buf
,
mtu
);
if
(
ret
<
0
)
{
...
...
@@ -556,13 +560,6 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
mtu
,
veth1buf
);
goto
out_del
;
}
ret
=
lxc_netdev_set_mtu
(
veth2buf
,
mtu
);
if
(
ret
<
0
)
{
usernic_error
(
"Failed to set mtu to %d on %s
\n
"
,
mtu
,
veth2buf
);
goto
out_del
;
}
}
/* attach veth1 to bridge */
...
...
@@ -573,14 +570,6 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
}
}
/* pass veth2 to target netns */
ret
=
lxc_netdev_move_by_name
(
veth2buf
,
pid
,
NULL
);
if
(
ret
<
0
)
{
usernic_error
(
"Error moving %s to network namespace of %d
\n
"
,
veth2buf
,
pid
);
goto
out_del
;
}
*
cnic
=
strdup
(
veth2buf
);
if
(
!*
cnic
)
{
usernic_error
(
"Failed to copy string
\"
%s
\"\n
"
,
veth2buf
);
...
...
src/lxc/network.c
View file @
6f6bd412
...
...
@@ -47,6 +47,7 @@
lxc_log_define
(
network
,
lxc
);
typedef
int
(
*
instantiate_cb
)(
struct
lxc_handler
*
,
struct
lxc_netdev
*
);
typedef
int
(
*
instantiate_ns_cb
)(
struct
lxc_netdev
*
);
static
const
char
loop_device
[]
=
"lo"
;
static
int
lxc_ip_route_dest
(
__u16
nlmsg_type
,
int
family
,
int
ifindex
,
void
*
dest
,
unsigned
int
netmask
)
...
...
@@ -271,10 +272,10 @@ static int lxc_is_ip_forwarding_enabled(const char *ifname, int family)
static
int
instantiate_veth
(
struct
lxc_handler
*
handler
,
struct
lxc_netdev
*
netdev
)
{
int
bridge_index
,
err
;
int
err
;
unsigned
int
mtu
;
char
*
veth1
,
*
veth2
;
char
veth1buf
[
IFNAMSIZ
],
veth2buf
[
IFNAMSIZ
];
unsigned
int
mtu
=
0
;
if
(
netdev
->
priv
.
veth_attr
.
pair
[
0
]
!=
'\0'
)
{
veth1
=
netdev
->
priv
.
veth_attr
.
pair
;
...
...
@@ -299,13 +300,25 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
veth2
=
lxc_mkifname
(
veth2buf
);
if
(
!
veth2
)
goto
out_delete
;
return
-
1
;
if
(
netdev
->
mtu
&&
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
))
{
return
log_error_errno
(
-
1
,
errno
,
"Failed to parse mtu"
);
}
else
if
(
netdev
->
link
[
0
]
!=
'\0'
)
{
int
ifindex_mtu
;
err
=
lxc_veth_create
(
veth1
,
veth2
);
ifindex_mtu
=
if_nametoindex
(
netdev
->
link
);
if
(
ifindex_mtu
)
{
mtu
=
netdev_get_mtu
(
ifindex_mtu
);
INFO
(
"Retrieved mtu %d from %s"
,
mtu
,
netdev
->
link
);
}
}
err
=
lxc_veth_create
(
veth1
,
veth2
,
handler
->
pid
,
mtu
);
if
(
err
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to create veth pair
\"
%s
\"
and
\"
%s
\"
"
,
veth1
,
veth2
);
goto
out_delete
;
return
-
1
;
}
strlcpy
(
netdev
->
created_name
,
veth2
,
IFNAMSIZ
);
...
...
@@ -327,42 +340,11 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
goto
out_delete
;
}
/* Note that we're retrieving the container's ifindex in the host's
* network namespace because we need it to move the device from the
* host's network namespace to the container's network namespace later
* on.
*/
netdev
->
ifindex
=
if_nametoindex
(
veth2
);
if
(
!
netdev
->
ifindex
)
{
ERROR
(
"Failed to retrieve ifindex for
\"
%s
\"
"
,
veth2
);
goto
out_delete
;
}
if
(
netdev
->
mtu
)
{
if
(
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
)
<
0
)
WARN
(
"Failed to parse mtu"
);
else
INFO
(
"Retrieved mtu %d"
,
mtu
);
}
else
if
(
netdev
->
link
[
0
]
!=
'\0'
)
{
bridge_index
=
if_nametoindex
(
netdev
->
link
);
if
(
bridge_index
)
{
mtu
=
netdev_get_mtu
(
bridge_index
);
INFO
(
"Retrieved mtu %d from %s"
,
mtu
,
netdev
->
link
);
}
else
{
mtu
=
netdev_get_mtu
(
netdev
->
ifindex
);
INFO
(
"Retrieved mtu %d from %s"
,
mtu
,
veth2
);
}
}
if
(
mtu
)
{
err
=
lxc_netdev_set_mtu
(
veth1
,
mtu
);
if
(
!
err
)
err
=
lxc_netdev_set_mtu
(
veth2
,
mtu
);
if
(
err
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set mtu
\"
%d
\"
for veth pair
\"
%s
\"
"
"and
\"
%s
\"
"
,
mtu
,
veth1
,
veth2
);
SYSERROR
(
"Failed to set mtu
\"
%d
\"
for veth pair
\"
%s
\"
"
,
mtu
,
veth1
);
goto
out_delete
;
}
}
...
...
@@ -484,14 +466,12 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
goto
out_delete
;
}
DEBUG
(
"Instantiated veth
\"
%s/%s
\"
, index is
\"
%d
\"
"
,
veth1
,
veth2
,
netdev
->
ifindex
);
DEBUG
(
"Instantiated veth tunnel
\"
%s <--> %s
\"
"
,
veth1
,
veth2
);
return
0
;
out_delete:
if
(
netdev
->
ifindex
!=
0
)
lxc_netdev_delete_by_name
(
veth1
);
lxc_netdev_delete_by_name
(
veth1
);
return
-
1
;
}
...
...
@@ -499,7 +479,6 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
{
char
peer
[
IFNAMSIZ
];
int
err
;
unsigned
int
mtu
=
0
;
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
ERROR
(
"No link for macvlan network device specified"
);
...
...
@@ -523,6 +502,8 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
}
strlcpy
(
netdev
->
created_name
,
peer
,
IFNAMSIZ
);
if
(
netdev
->
name
[
0
]
==
'\0'
)
(
void
)
strlcpy
(
netdev
->
name
,
peer
,
IFNAMSIZ
);
netdev
->
ifindex
=
if_nametoindex
(
peer
);
if
(
!
netdev
->
ifindex
)
{
...
...
@@ -531,6 +512,8 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
}
if
(
netdev
->
mtu
)
{
unsigned
int
mtu
;
err
=
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
...
...
@@ -661,7 +644,6 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
{
char
peer
[
IFNAMSIZ
];
int
err
;
unsigned
int
mtu
=
0
;
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
ERROR
(
"No link for ipvlan network device specified"
);
...
...
@@ -684,6 +666,8 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
}
strlcpy
(
netdev
->
created_name
,
peer
,
IFNAMSIZ
);
if
(
netdev
->
name
[
0
]
==
'\0'
)
(
void
)
strlcpy
(
netdev
->
name
,
peer
,
IFNAMSIZ
);
netdev
->
ifindex
=
if_nametoindex
(
peer
);
if
(
!
netdev
->
ifindex
)
{
...
...
@@ -692,19 +676,19 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
}
if
(
netdev
->
mtu
)
{
unsigned
int
mtu
;
err
=
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to parse mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
SYSERROR
(
"Failed to parse mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
goto
on_error
;
}
err
=
lxc_netdev_set_mtu
(
peer
,
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
goto
on_error
;
}
}
...
...
@@ -737,7 +721,6 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
char
peer
[
IFNAMSIZ
];
int
err
;
static
uint16_t
vlan_cntr
=
0
;
unsigned
int
mtu
=
0
;
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
ERROR
(
"No link for vlan network device specified"
);
...
...
@@ -758,6 +741,8 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
}
strlcpy
(
netdev
->
created_name
,
peer
,
IFNAMSIZ
);
if
(
netdev
->
name
[
0
]
==
'\0'
)
(
void
)
strlcpy
(
netdev
->
name
,
peer
,
IFNAMSIZ
);
netdev
->
ifindex
=
if_nametoindex
(
peer
);
if
(
!
netdev
->
ifindex
)
{
...
...
@@ -766,19 +751,19 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
}
if
(
netdev
->
mtu
)
{
unsigned
int
mtu
;
err
=
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to parse mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
SYSERROR
(
"Failed to parse mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
goto
on_error
;
}
err
=
lxc_netdev_set_mtu
(
peer
,
mtu
);
if
(
err
)
{
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
peer
);
goto
on_error
;
}
}
...
...
@@ -810,7 +795,6 @@ on_error:
static
int
instantiate_phys
(
struct
lxc_handler
*
handler
,
struct
lxc_netdev
*
netdev
)
{
int
err
,
mtu_orig
=
0
;
unsigned
int
mtu
=
0
;
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
ERROR
(
"No link for physical interface specified"
);
...
...
@@ -832,6 +816,8 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
}
strlcpy
(
netdev
->
created_name
,
netdev
->
link
,
IFNAMSIZ
);
if
(
netdev
->
name
[
0
]
==
'\0'
)
(
void
)
strlcpy
(
netdev
->
name
,
netdev
->
link
,
IFNAMSIZ
);
/*
* Store the ifindex of the host's network device in the host's
...
...
@@ -852,6 +838,8 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
netdev
->
priv
.
phys_attr
.
mtu
=
mtu_orig
;
if
(
netdev
->
mtu
)
{
unsigned
int
mtu
;
err
=
lxc_safe_uint
(
netdev
->
mtu
,
&
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
...
...
@@ -863,8 +851,7 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
err
=
lxc_netdev_set_mtu
(
netdev
->
link
,
mtu
);
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
netdev
->
link
);
SYSERROR
(
"Failed to set mtu
\"
%s
\"
for interface
\"
%s
\"
"
,
netdev
->
mtu
,
netdev
->
link
);
return
-
1
;
}
}
...
...
@@ -925,6 +912,102 @@ static instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
[
LXC_NET_NONE
]
=
instantiate_none
,
};
static
int
instantiate_ns_veth
(
struct
lxc_netdev
*
netdev
)
{
char
current_ifname
[
IFNAMSIZ
];
netdev
->
ifindex
=
if_nametoindex
(
netdev
->
created_name
);
if
(
!
netdev
->
ifindex
)
return
log_error_errno
(
-
1
,
errno
,
"Failed to retrieve ifindex for network device with name %s"
,
netdev
->
created_name
);
if
(
netdev
->
name
[
0
]
==
'\0'
)
(
void
)
strlcpy
(
netdev
->
name
,
"eth%d"
,
IFNAMSIZ
);
if
(
strcmp
(
netdev
->
created_name
,
netdev
->
name
)
!=
0
)
{
int
ret
;
ret
=
lxc_netdev_rename_by_name
(
netdev
->
created_name
,
netdev
->
name
);
if
(
ret
)
return
log_error_errno
(
-
1
,
-
ret
,
"Failed to rename network device
\"
%s
\"
to
\"
%s
\"
"
,
netdev
->
created_name
,
netdev
->
name
);
TRACE
(
"Renamed network device from
\"
%s
\"
to
\"
%s
\"
"
,
netdev
->
created_name
,
netdev
->
name
);
}
/*
* Re-read the name of the interface because its name has changed and
* would be automatically allocated by the system
*/
if
(
!
if_indextoname
(
netdev
->
ifindex
,
current_ifname
))
return
log_error_errno
(
-
1
,
errno
,
"Failed get name for network device with ifindex %d"
,
netdev
->
ifindex
);
/*
* Now update the recorded name of the network device to reflect the
* name of the network device in the child's network namespace. We will
* later on send this information back to the parent.
*/
(
void
)
strlcpy
(
netdev
->
name
,
current_ifname
,
IFNAMSIZ
);
return
0
;
}
static
int
__instantiate_common
(
struct
lxc_netdev
*
netdev
)
{
netdev
->
ifindex
=
if_nametoindex
(
netdev
->
name
);
if
(
!
netdev
->
ifindex
)
return
log_error_errno
(
-
1
,
errno
,
"Failed to retrieve ifindex for network device with name %s"
,
netdev
->
name
);
return
0
;
}
static
int
instantiate_ns_macvlan
(
struct
lxc_netdev
*
netdev
)
{
return
__instantiate_common
(
netdev
);
}
static
int
instantiate_ns_ipvlan
(
struct
lxc_netdev
*
netdev
)
{
return
__instantiate_common
(
netdev
);
}
static
int
instantiate_ns_vlan
(
struct
lxc_netdev
*
netdev
)
{
return
__instantiate_common
(
netdev
);
}
static
int
instantiate_ns_phys
(
struct
lxc_netdev
*
netdev
)
{
return
__instantiate_common
(
netdev
);
}
static
int
instantiate_ns_empty
(
struct
lxc_netdev
*
netdev
)
{
return
0
;
}
static
int
instantiate_ns_none
(
struct
lxc_netdev
*
netdev
)
{
return
0
;
}
static
instantiate_ns_cb
netdev_ns_conf
[
LXC_NET_MAXCONFTYPE
+
1
]
=
{
[
LXC_NET_VETH
]
=
instantiate_ns_veth
,
[
LXC_NET_MACVLAN
]
=
instantiate_ns_macvlan
,
[
LXC_NET_IPVLAN
]
=
instantiate_ns_ipvlan
,
[
LXC_NET_VLAN
]
=
instantiate_ns_vlan
,
[
LXC_NET_PHYS
]
=
instantiate_ns_phys
,
[
LXC_NET_EMPTY
]
=
instantiate_ns_empty
,
[
LXC_NET_NONE
]
=
instantiate_ns_none
,
};
static
int
shutdown_veth
(
struct
lxc_handler
*
handler
,
struct
lxc_netdev
*
netdev
)
{
int
ret
;
...
...
@@ -1642,7 +1725,7 @@ out:
int
lxc_netdev_set_mtu
(
const
char
*
name
,
int
mtu
)
{
int
err
,
index
,
len
;
int
err
,
len
;
struct
ifinfomsg
*
ifi
;
struct
nl_handler
nlh
;
struct
nlmsg
*
answer
=
NULL
,
*
nlmsg
=
NULL
;
...
...
@@ -1665,11 +1748,6 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
if
(
!
answer
)
goto
out
;
err
=
-
EINVAL
;
index
=
if_nametoindex
(
name
);
if
(
!
index
)
goto
out
;
nlmsg
->
nlmsghdr
->
nlmsg_flags
=
NLM_F_REQUEST
|
NLM_F_ACK
;
nlmsg
->
nlmsghdr
->
nlmsg_type
=
RTM_NEWLINK
;
...
...
@@ -1679,7 +1757,9 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
goto
out
;
}
ifi
->
ifi_family
=
AF_UNSPEC
;
ifi
->
ifi_index
=
index
;
if
(
nla_put_string
(
nlmsg
,
IFLA_IFNAME
,
name
))
goto
out
;
if
(
nla_put_u32
(
nlmsg
,
IFLA_MTU
,
mtu
))
goto
out
;
...
...
@@ -1702,7 +1782,7 @@ int lxc_netdev_down(const char *name)
return
netdev_set_flag
(
name
,
0
);
}
int
lxc_veth_create
(
const
char
*
name1
,
const
char
*
name2
)
int
lxc_veth_create
(
const
char
*
name1
,
const
char
*
name2
,
pid_t
pid
,
unsigned
int
mtu
)
{
int
err
,
len
;
struct
ifinfomsg
*
ifi
;
...
...
@@ -1766,6 +1846,12 @@ int lxc_veth_create(const char *name1, const char *name2)
if
(
nla_put_string
(
nlmsg
,
IFLA_IFNAME
,
name2
))
goto
out
;
if
(
mtu
>
0
&&
nla_put_u32
(
nlmsg
,
IFLA_MTU
,
mtu
))
goto
out
;
if
(
pid
>
0
&&
nla_put_u32
(
nlmsg
,
IFLA_NET_NS_PID
,
pid
))
goto
out
;
nla_end_nested
(
nlmsg
,
nest3
);
nla_end_nested
(
nlmsg
,
nest2
);
nla_end_nested
(
nlmsg
,
nest1
);
...
...
@@ -3018,9 +3104,10 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
netdev
->
link
);
clear_ifindices:
/* We need to clear any ifindices we recorded so liblxc won't
* have cached stale data which would cause it to fail on reboot
* we're we don't re-read the on-disk config file.
/*
* We need to clear any ifindices we recorded so liblxc won't
* have cached stale data which would cause it to fail on
* reboot where we don't re-read the on-disk config file.
*/
netdev
->
ifindex
=
0
;
if
(
netdev
->
type
==
LXC_NET_PHYS
)
{
...
...
@@ -3267,7 +3354,7 @@ int lxc_network_move_created_netdev_priv(struct lxc_handler *handler)
if
(
physname
)
ret
=
lxc_netdev_move_wlan
(
physname
,
netdev
->
link
,
pid
,
NULL
);
else
ret
=
lxc_netdev_move_by_index
(
netdev
->
ifindex
,
pid
,
NULL
);
ret
=
lxc_netdev_move_by_index
(
netdev
->
ifindex
,
pid
,
netdev
->
name
);
if
(
ret
)
{
errno
=
-
ret
;
SYSERROR
(
"Failed to move network device
\"
%s
\"
with ifindex %d to network namespace %d"
,
...
...
@@ -3341,6 +3428,12 @@ bool lxc_delete_network_priv(struct lxc_handler *handler)
if
(
!
netdev
->
ifindex
)
continue
;
/*
* If the network device has been moved back from the
* containers network namespace, update the ifindex.
*/
netdev
->
ifindex
=
if_nametoindex
(
netdev
->
name
);
/* Delete l2proxy entries if enabled and used with a link property */
if
(
netdev
->
l2proxy
&&
netdev
->
link
[
0
]
!=
'\0'
)
{
if
(
lxc_delete_l2proxy
(
netdev
))
...
...
@@ -3379,26 +3472,6 @@ bool lxc_delete_network_priv(struct lxc_handler *handler)
if
(
ret
<
0
)
WARN
(
"Failed to deconfigure network device"
);
/* Recent kernels remove the virtual interfaces when the network
* namespace is destroyed but in case we did not move the
* interface to the network namespace, we have to destroy it.
*/
ret
=
lxc_netdev_delete_by_index
(
netdev
->
ifindex
);
if
(
ret
<
0
)
{
if
(
errno
!=
ENODEV
)
{
WARN
(
"Failed to remove interface
\"
%s
\"
with index %d"
,
netdev
->
name
[
0
]
!=
'\0'
?
netdev
->
name
:
"(null)"
,
netdev
->
ifindex
);
goto
clear_ifindices
;
}
INFO
(
"Interface
\"
%s
\"
with index %d already deleted or existing in different network namespace"
,
netdev
->
name
[
0
]
!=
'\0'
?
netdev
->
name
:
"(null)"
,
netdev
->
ifindex
);
}
INFO
(
"Removed interface
\"
%s
\"
with index %d"
,
netdev
->
name
[
0
]
!=
'\0'
?
netdev
->
name
:
"(null)"
,
netdev
->
ifindex
);
if
(
netdev
->
type
!=
LXC_NET_VETH
)
goto
clear_ifindices
;
...
...
@@ -3617,98 +3690,26 @@ static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
return
0
;
}
static
int
lxc_
setup_netdev_in_child_namespaces
(
struct
lxc_netdev
*
netdev
)
static
int
lxc_
network_setup_in_child_namespaces_common
(
struct
lxc_netdev
*
netdev
)
{
char
ifname
[
IFNAMSIZ
];
int
err
;
char
*
current_ifname
=
ifname
;
char
bufinet4
[
INET_ADDRSTRLEN
],
bufinet6
[
INET6_ADDRSTRLEN
];
/* empty network namespace */
if
(
!
netdev
->
ifindex
)
{
if
(
netdev
->
flags
&
IFF_UP
)
{
err
=
lxc_netdev_up
(
"lo"
);
if
(
err
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set the loopback network device up"
);
return
-
1
;
}
}
if
(
netdev
->
type
==
LXC_NET_EMPTY
)
return
0
;
if
(
netdev
->
type
==
LXC_NET_NONE
)
return
0
;
netdev
->
ifindex
=
if_nametoindex
(
netdev
->
created_name
);
if
(
!
netdev
->
ifindex
)
SYSERROR
(
"Failed to retrieve ifindex for network device with name %s"
,
netdev
->
created_name
?:
"(null)"
);
}
/* get the new ifindex in case of physical netdev */
if
(
netdev
->
type
==
LXC_NET_PHYS
)
{
netdev
->
ifindex
=
if_nametoindex
(
netdev
->
link
);
if
(
!
netdev
->
ifindex
)
{
ERROR
(
"Failed to get ifindex for network device
\"
%s
\"
"
,
netdev
->
link
);
return
-
1
;
}
}
/* retrieve the name of the interface */
if
(
!
if_indextoname
(
netdev
->
ifindex
,
current_ifname
))
{
SYSERROR
(
"Failed to retrieve name for network device with ifindex %d"
,
netdev
->
ifindex
);
return
-
1
;
}
/* Default: let the system choose an interface name.
* When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
* netlink will replace the format specifier with an appropriate index.
*/
if
(
netdev
->
name
[
0
]
==
'\0'
)
{
if
(
netdev
->
type
==
LXC_NET_PHYS
)
(
void
)
strlcpy
(
netdev
->
name
,
netdev
->
link
,
IFNAMSIZ
);
else
(
void
)
strlcpy
(
netdev
->
name
,
"eth%d"
,
IFNAMSIZ
);
}
/* rename the interface name */
if
(
strcmp
(
current_ifname
,
netdev
->
name
)
!=
0
)
{
err
=
lxc_netdev_rename_by_name
(
current_ifname
,
netdev
->
name
);
if
(
!
netdev
->
ifindex
&&
netdev
->
flags
&
IFF_UP
)
{
err
=
lxc_netdev_up
(
"lo"
);
if
(
err
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to rename network device
\"
%s
\"
to
\"
%s
\"
"
,
current_ifname
,
netdev
->
name
);
SYSERROR
(
"Failed to set the loopback network device up"
);
return
-
1
;
}
TRACE
(
"Renamed network device from
\"
%s
\"
to
\"
%s
\"
"
,
current_ifname
,
netdev
->
name
);
}
/* Re-read the name of the interface because its name has changed
* and would be automatically allocated by the system
*/
if
(
!
if_indextoname
(
netdev
->
ifindex
,
current_ifname
))
{
ERROR
(
"Failed get name for network device with ifindex %d"
,
netdev
->
ifindex
);
return
-
1
;
}
/* Now update the recorded name of the network device to reflect the
* name of the network device in the child's network namespace. We will
* later on send this information back to the parent.
*/
(
void
)
strlcpy
(
netdev
->
name
,
current_ifname
,
IFNAMSIZ
);
/* set a mac address */
if
(
netdev
->
hwaddr
)
{
if
(
setup_hw_addr
(
netdev
->
hwaddr
,
current_if
name
))
{
if
(
setup_hw_addr
(
netdev
->
hwaddr
,
netdev
->
name
))
{
ERROR
(
"Failed to setup hw address for network device
\"
%s
\"
"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
}
...
...
@@ -3716,24 +3717,24 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
/* setup ipv4 addresses on the interface */
if
(
setup_ipv4_addr
(
&
netdev
->
ipv4
,
netdev
->
ifindex
))
{
ERROR
(
"Failed to setup ip addresses for network device
\"
%s
\"
"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
/* setup ipv6 addresses on the interface */
if
(
setup_ipv6_addr
(
&
netdev
->
ipv6
,
netdev
->
ifindex
))
{
ERROR
(
"Failed to setup ipv6 addresses for network device
\"
%s
\"
"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
/* set the network device up */
if
(
netdev
->
flags
&
IFF_UP
)
{
err
=
lxc_netdev_up
(
current_if
name
);
err
=
lxc_netdev_up
(
netdev
->
name
);
if
(
err
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to set network device
\"
%s
\"
up"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
...
...
@@ -3750,13 +3751,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
netdev
->
ipv4_gateway
||
netdev
->
ipv4_gateway_dev
)
{
if
(
!
(
netdev
->
flags
&
IFF_UP
))
{
ERROR
(
"Cannot add ipv4 gateway for network device "
"
\"
%s
\"
when not bringing up the interface"
,
current_if
name
);
"
\"
%s
\"
when not bringing up the interface"
,
netdev
->
name
);
return
-
1
;
}
if
(
lxc_list_empty
(
&
netdev
->
ipv4
))
{
ERROR
(
"Cannot add ipv4 gateway for network device "
"
\"
%s
\"
when not assigning an address"
,
current_if
name
);
"
\"
%s
\"
when not assigning an address"
,
netdev
->
name
);
return
-
1
;
}
...
...
@@ -3765,7 +3766,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
err
=
lxc_ipv4_gateway_add
(
netdev
->
ifindex
,
NULL
);
if
(
err
<
0
)
{
SYSERROR
(
"Failed to setup ipv4 gateway to network device
\"
%s
\"
"
,
current_if
name
);
netdev
->
name
);
return
ret_set_errno
(
-
1
,
-
err
);
}
}
else
{
...
...
@@ -3785,7 +3786,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to add ipv4 dest
\"
%s
\"
for network device
\"
%s
\"
"
,
bufinet4
,
current_if
name
);
bufinet4
,
netdev
->
name
);
return
-
1
;
}
...
...
@@ -3793,7 +3794,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to setup ipv4 gateway
\"
%s
\"
for network device
\"
%s
\"
"
,
bufinet4
,
current_if
name
);
bufinet4
,
netdev
->
name
);
return
-
1
;
}
}
...
...
@@ -3804,13 +3805,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
netdev
->
ipv6_gateway
||
netdev
->
ipv6_gateway_dev
)
{
if
(
!
(
netdev
->
flags
&
IFF_UP
))
{
ERROR
(
"Cannot add ipv6 gateway for network device
\"
%s
\"
when not bringing up the interface"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
if
(
lxc_list_empty
(
&
netdev
->
ipv6
)
&&
!
IN6_IS_ADDR_LINKLOCAL
(
netdev
->
ipv6_gateway
))
{
ERROR
(
"Cannot add ipv6 gateway for network device
\"
%s
\"
when not assigning an address"
,
current_if
name
);
netdev
->
name
);
return
-
1
;
}
...
...
@@ -3819,7 +3820,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
err
=
lxc_ipv6_gateway_add
(
netdev
->
ifindex
,
NULL
);
if
(
err
<
0
)
{
SYSERROR
(
"Failed to setup ipv6 gateway to network device
\"
%s
\"
"
,
current_if
name
);
netdev
->
name
);
return
ret_set_errno
(
-
1
,
-
err
);
}
}
else
{
...
...
@@ -3839,7 +3840,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to add ipv6 dest
\"
%s
\"
for network device
\"
%s
\"
"
,
bufinet6
,
current_if
name
);
bufinet6
,
netdev
->
name
);
return
-
1
;
}
...
...
@@ -3847,14 +3848,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if
(
err
<
0
)
{
errno
=
-
err
;
SYSERROR
(
"Failed to setup ipv6 gateway
\"
%s
\"
for network device
\"
%s
\"
"
,
bufinet6
,
current_if
name
);
bufinet6
,
netdev
->
name
);
return
-
1
;
}
}
}
}
DEBUG
(
"Network device
\"
%s
\"
has been setup"
,
current_if
name
);
DEBUG
(
"Network device
\"
%s
\"
has been setup"
,
netdev
->
name
);
return
0
;
}
...
...
@@ -3864,10 +3865,14 @@ int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
{
struct
lxc_list
*
iterator
;
lxc_list_for_each
(
iterator
,
network
)
{
lxc_list_for_each
(
iterator
,
network
)
{
struct
lxc_netdev
*
netdev
=
iterator
->
elem
;
int
ret
;
if
(
lxc_setup_netdev_in_child_namespaces
(
netdev
))
{
ret
=
netdev_ns_conf
[
netdev
->
type
](
netdev
);
if
(
!
ret
)
ret
=
lxc_network_setup_in_child_namespaces_common
(
netdev
);
if
(
ret
)
{
ERROR
(
"Failed to setup netdev"
);
return
-
1
;
}
...
...
@@ -3926,6 +3931,7 @@ int lxc_network_recv_from_parent(struct lxc_handler *handler)
ret
=
lxc_recv_nointr
(
data_sock
,
netdev
->
created_name
,
IFNAMSIZ
,
0
);
if
(
ret
<
0
)
return
-
1
;
TRACE
(
"Received network device name
\"
%s
\"
from parent"
,
netdev
->
created_name
);
}
...
...
src/lxc/network.h
View file @
6f6bd412
...
...
@@ -203,7 +203,8 @@ extern int lxc_netdev_down(const char *name);
extern
int
lxc_netdev_set_mtu
(
const
char
*
name
,
int
mtu
);
/* Create a virtual network devices. */
extern
int
lxc_veth_create
(
const
char
*
name1
,
const
char
*
name2
);
extern
int
lxc_veth_create
(
const
char
*
name1
,
const
char
*
name2
,
pid_t
pid
,
unsigned
int
mtu
);
extern
int
lxc_macvlan_create
(
const
char
*
master
,
const
char
*
name
,
int
mode
);
extern
int
lxc_vlan_create
(
const
char
*
master
,
const
char
*
name
,
unsigned
short
vid
);
...
...
src/tests/api_reboot.c
View file @
6f6bd412
...
...
@@ -29,17 +29,46 @@
#include "lxc/lxccontainer.h"
#include "lxctest.h"
#include "utils.h"
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
#endif
#define TSTNAME "lxc-api-reboot"
int
main
(
int
argc
,
char
*
argv
[])
{
int
i
;
struct
lxc_container
*
c
;
int
ret
=
EXIT_FAILURE
;
struct
lxc_log
log
;
char
template
[
sizeof
(
P_tmpdir
"/reboot_XXXXXX"
)];
(
void
)
strlcpy
(
template
,
P_tmpdir
"/reboot_XXXXXX"
,
sizeof
(
template
));
i
=
lxc_make_tmpfile
(
template
,
false
);
if
(
i
<
0
)
{
lxc_error
(
"Failed to create temporary log file for container %s
\n
"
,
TSTNAME
);
exit
(
EXIT_FAILURE
);
}
else
{
lxc_debug
(
"Using
\"
%s
\"
as temporary log file for container %s
\n
"
,
template
,
TSTNAME
);
close
(
i
);
}
log
.
name
=
TSTNAME
;
log
.
file
=
template
;
log
.
level
=
"TRACE"
;
log
.
prefix
=
"reboot"
;
log
.
quiet
=
false
;
log
.
lxcpath
=
NULL
;
if
(
lxc_log_init
(
&
log
))
exit
(
ret
);
/* Test that the reboot() API function properly waits for containers to
* restart.
*/
c
=
lxc_container_new
(
"reboot"
,
NULL
);
c
=
lxc_container_new
(
TSTNAME
,
NULL
);
if
(
!
c
)
{
lxc_error
(
"%s"
,
"Failed to create container
\"
reboot
\"
"
);
exit
(
ret
);
...
...
@@ -120,8 +149,24 @@ on_error_stop:
on_error_put:
lxc_container_put
(
c
);
if
(
ret
==
EXIT_SUCCESS
)
if
(
ret
==
EXIT_SUCCESS
)
{
lxc_debug
(
"%s
\n
"
,
"All reboot tests passed"
);
}
else
{
int
fd
;
fd
=
open
(
template
,
O_RDONLY
);
if
(
fd
>=
0
)
{
char
buf
[
4096
];
ssize_t
buflen
;
while
((
buflen
=
read
(
fd
,
buf
,
1024
))
>
0
)
{
buflen
=
write
(
STDERR_FILENO
,
buf
,
buflen
);
if
(
buflen
<=
0
)
break
;
}
close
(
fd
);
}
}
(
void
)
unlink
(
template
);
exit
(
ret
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment