mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Implement IFLA_IFNAME which specifies an interface's name.
IFLA_IFNAME is used to set an interface's name when being used with RTM_NEWLINK and RTM_SETLINK. RTM_NEWLINK is the preferred way, it is backwards compatible with RTM_SETLINK. For gVisor, when RTM_SETLINK is introduced, it shall just share the implementation. PiperOrigin-RevId: 647833657
This commit is contained in:
@@ -123,15 +123,13 @@ func (s *Stack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Er
|
||||
if len(value) < 1 {
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
if ifinfomsg.Index != 0 {
|
||||
// Device name changing isn't supported yet.
|
||||
return syserr.ErrNotSupported
|
||||
}
|
||||
ifname = value.String()
|
||||
for idx, ifa := range s.Interfaces() {
|
||||
if ifname == ifa.Name {
|
||||
ifinfomsg.Index = idx
|
||||
break
|
||||
if ifinfomsg.Index == 0 {
|
||||
ifname = value.String()
|
||||
for idx, ifa := range s.Interfaces() {
|
||||
if ifname == ifa.Name {
|
||||
ifinfomsg.Index = idx
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case linux.IFLA_MASTER:
|
||||
@@ -190,6 +188,10 @@ func (s *Stack) setLink(id tcpip.NICID, linkAttrs map[uint16]nlmsg.BytesView) *s
|
||||
if err := s.Stack.SetNICAddress(id, addr); err != nil {
|
||||
return syserr.TranslateNetstackError(err)
|
||||
}
|
||||
case linux.IFLA_IFNAME:
|
||||
if err := s.Stack.SetNICName(id, v.String()); err != nil {
|
||||
return syserr.TranslateNetstackError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1057,6 +1057,19 @@ func (s *Stack) SetNICAddress(id tcpip.NICID, addr tcpip.LinkAddress) tcpip.Erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetNICName sets a NIC's name.
|
||||
func (s *Stack) SetNICName(id tcpip.NICID, name string) tcpip.Error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
nic, ok := s.nics[id]
|
||||
if !ok {
|
||||
return &tcpip.ErrUnknownNICID{}
|
||||
}
|
||||
nic.name = name
|
||||
return nil
|
||||
}
|
||||
|
||||
// NICInfo captures the name and addresses assigned to a NIC.
|
||||
type NICInfo struct {
|
||||
Name string
|
||||
|
||||
@@ -30,6 +30,17 @@ if ! wait_for ! ip link show test_veth02; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a new veth pair in the current namespace and rename the link.
|
||||
ip link add name test_veth01 type veth peer name test_veth02
|
||||
ip link set test_veth01 name test_veth03
|
||||
ip link show test_veth03
|
||||
ip link del name test_veth03
|
||||
# Check that test_veth02 has been destroyed.
|
||||
if ! wait_for ! ip link show test_veth02; then
|
||||
fail "test_veth02 hasn't been destroyed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ip netns add test
|
||||
ip link add test_veth01 type veth peer name test_veth02 netns test
|
||||
ip link show test_veth01
|
||||
|
||||
@@ -200,6 +200,64 @@ TEST(NetlinkRouteTest, GetLinkByIndex) {
|
||||
EXPECT_TRUE(found) << "Netlink response does not contain any links.";
|
||||
}
|
||||
|
||||
TEST(NetlinkRouteTest, ChangeLinkName) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
|
||||
SKIP_IF(IsRunningWithHostinet());
|
||||
// Hosts that run with old kernel allow renaming only when
|
||||
// the interface is down. The restriction has been removed.
|
||||
SKIP_IF(!IsRunningOnGvisor());
|
||||
Link loopback_link = ASSERT_NO_ERRNO_AND_VALUE(LoopbackLink());
|
||||
|
||||
FileDescriptor fd =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE));
|
||||
|
||||
struct request {
|
||||
struct nlmsghdr hdr;
|
||||
struct ifinfomsg ifm;
|
||||
struct rtattr rtattr;
|
||||
char ifname[IFNAMSIZ];
|
||||
char pad[NLMSG_ALIGNTO + RTA_ALIGNTO];
|
||||
};
|
||||
|
||||
const std::string new_linkname = "notloopback";
|
||||
|
||||
// Change the link name.
|
||||
struct request req = {};
|
||||
req.hdr.nlmsg_len = sizeof(req);
|
||||
req.hdr.nlmsg_type = RTM_NEWLINK;
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
req.hdr.nlmsg_seq = kSeq;
|
||||
req.ifm.ifi_family = AF_UNSPEC;
|
||||
req.ifm.ifi_index = loopback_link.index;
|
||||
req.rtattr.rta_type = IFLA_IFNAME;
|
||||
req.rtattr.rta_len = RTA_LENGTH(new_linkname.size() + 1);
|
||||
strncpy(req.ifname, new_linkname.c_str(), sizeof(req.ifname));
|
||||
req.hdr.nlmsg_len =
|
||||
NLMSG_LENGTH(sizeof(req.ifm)) + NLMSG_ALIGN(req.rtattr.rta_len);
|
||||
EXPECT_NO_ERRNO(NetlinkRequestAckOrError(fd, kSeq, &req, sizeof(req)));
|
||||
|
||||
// Search the link by the new name.
|
||||
loopback_link.name = new_linkname;
|
||||
req.hdr.nlmsg_type = RTM_GETLINK;
|
||||
req.ifm.ifi_index = 0;
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.rtattr.rta_type = IFLA_IFNAME;
|
||||
req.rtattr.rta_len = RTA_LENGTH(new_linkname.size() + 1);
|
||||
strncpy(req.ifname, new_linkname.c_str(), sizeof(req.ifname));
|
||||
req.hdr.nlmsg_len =
|
||||
NLMSG_LENGTH(sizeof(req.ifm)) + NLMSG_ALIGN(req.rtattr.rta_len);
|
||||
|
||||
bool found = false;
|
||||
ASSERT_NO_ERRNO(NetlinkRequestResponse(
|
||||
fd, &req, sizeof(req),
|
||||
[&](const struct nlmsghdr* hdr) {
|
||||
CheckLinkMsg(hdr, loopback_link);
|
||||
found = true;
|
||||
},
|
||||
false));
|
||||
EXPECT_TRUE(found) << "Netlink response does not contain any links.";
|
||||
}
|
||||
|
||||
TEST(NetlinkRouteTest, LinkUp) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
|
||||
SKIP_IF(IsRunningWithHostinet());
|
||||
|
||||
Reference in New Issue
Block a user