summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorErik Kline <ek@google.com>2014-10-06 20:25:36 +0900
committerLorenzo Colitti <lorenzo@google.com>2015-02-02 17:47:29 +0900
commitaca272212f10365ab66891b43c535eed7ef63f72 (patch)
treef066860789fd2e04672ba0268efc4aaa8271d720 /tests
parentd7c3975614112794fccf8a576d442c19e801daa8 (diff)
downloadextras-aca272212f10365ab66891b43c535eed7ef63f72.tar.gz
Add basic RTM_GETADDR support.
[iproute.py] - Basic RTM_GETADDR support (currently IPv6-only). - Add the rest of Linux's IFA_F_* flags values. [mark_test.py] - Fix comment typo. Bug: 17769720 Change-Id: I4e883a6e01c825ee0de75314f12c0892e96d5a15
Diffstat (limited to 'tests')
-rw-r--r--tests/net_test/iproute.py66
-rwxr-xr-xtests/net_test/mark_test.py2
2 files changed, 47 insertions, 21 deletions
diff --git a/tests/net_test/iproute.py b/tests/net_test/iproute.py
index dce85991..6c20c9cd 100644
--- a/tests/net_test/iproute.py
+++ b/tests/net_test/iproute.py
@@ -41,6 +41,7 @@ NLA_ALIGNTO = 4
# Message types.
RTM_NEWADDR = 20
RTM_DELADDR = 21
+RTM_GETADDR = 22
RTM_NEWROUTE = 24
RTM_DELROUTE = 25
RTM_GETROUTE = 26
@@ -93,14 +94,25 @@ RTACacheinfo = cstruct.Struct(
# Interface address attributes.
IFA_ADDRESS = 1
IFA_LOCAL = 2
+IFA_CACHEINFO = 6
# Address flags.
+IFA_F_SECONDARY = 0x01
+IFA_F_TEMPORARY = IFA_F_SECONDARY
+IFA_F_NODAD = 0x02
+IFA_F_OPTIMISTIC = 0x04
+IFA_F_DADFAILED = 0x08
+IFA_F_HOMEADDRESS = 0x10
+IFA_F_DEPRECATED = 0x20
+IFA_F_TENTATIVE = 0x40
IFA_F_PERMANENT = 0x80
# Data structure formats.
IfAddrMsg = cstruct.Struct(
"IfAddrMsg", "=BBBBI",
"family prefixlen flags scope index")
+IFACacheinfo = cstruct.Struct(
+ "IFACacheinfo", "=IIII", "prefered valid cstamp tstamp")
### Neighbour table entry constants. See include/uapi/linux/neighbour.h.
@@ -207,6 +219,8 @@ class IPRoute(object):
if command == -RTA_METRICS:
name = self._GetConstantName(nla_type, "RTAX_")
+ elif CommandSubject(command) == "ADDR":
+ name = self._GetConstantName(nla_type, "IFA_")
elif CommandSubject(command) == "RULE":
name = self._GetConstantName(nla_type, "FRA_")
elif CommandSubject(command) == "ROUTE":
@@ -219,8 +233,8 @@ class IPRoute(object):
"FRA_EXPERIMENTAL_UID_START", "FRA_EXPERIMENTAL_UID_END",
"RTA_OIF", "RTA_PRIORITY", "RTA_TABLE", "RTA_MARK"]:
data = struct.unpack("=I", nla_data)[0]
- elif name in ["RTA_DST", "RTA_SRC", "RTA_GATEWAY", "RTA_PREFSRC",
- "RTA_EXPERIMENTAL_UID"]:
+ elif name in ["IFA_ADDRESS", "IFA_LOCAL", "RTA_DST", "RTA_SRC",
+ "RTA_GATEWAY", "RTA_PREFSRC", "RTA_EXPERIMENTAL_UID"]:
data = socket.inet_ntop(family, nla_data)
elif name in ["FRA_IIFNAME", "FRA_OIFNAME"]:
data = nla_data.strip("\x00")
@@ -228,6 +242,8 @@ class IPRoute(object):
data = self._ParseAttributes(-RTA_METRICS, family, nla_data)
elif name == "RTA_CACHEINFO":
data = RTACacheinfo(nla_data)
+ elif name == "IFA_CACHEINFO":
+ data = IFACacheinfo(nla_data)
else:
data = nla_data
@@ -390,9 +406,8 @@ class IPRoute(object):
def UnreachableRule(self, version, is_add, priority):
return self._Rule(version, is_add, None, None, priority=priority)
- def _GetRTMsg(self, data):
- """Parses a RTMsg into a header and a dictionary of attributes."""
- # Parse the netlink and rtmsg headers.
+ def _ParseNLMsg(self, data, msgtype):
+ """Parses a Netlink message into a header and a dictionary of attributes."""
nlmsghdr, data = cstruct.Read(data, NLMsgHdr)
self._Debug(" %s" % nlmsghdr)
@@ -400,20 +415,20 @@ class IPRoute(object):
print "done"
return None, data
- rtmsg, data = cstruct.Read(data, RTMsg)
- self._Debug(" %s" % rtmsg)
+ nlmsg, data = cstruct.Read(data, msgtype)
+ self._Debug(" %s" % nlmsg)
- # Parse the attributes in the rtmsg.
- attrlen = nlmsghdr.length - len(nlmsghdr) - len(rtmsg)
- attributes = self._ParseAttributes(nlmsghdr.type, rtmsg.family,
+ # Parse the attributes in the nlmsg.
+ attrlen = nlmsghdr.length - len(nlmsghdr) - len(nlmsg)
+ attributes = self._ParseAttributes(nlmsghdr.type, nlmsg.family,
data[:attrlen])
data = data[attrlen:]
- return (rtmsg, attributes), data
+ return (nlmsg, attributes), data
def _GetRTMsgList(self, data, expect_done):
out = []
while data:
- msg, data = self._GetRTMsg(data)
+ msg, data = self._ParseNLMsg(data, RTMsg)
if msg is None:
break
out.append(msg)
@@ -437,24 +452,35 @@ class IPRoute(object):
data = self._Recv()
return self._GetRTMsgList(data, True)
- def _Address(self, version, is_add, addr, prefixlen, flags, scope, ifindex):
+ def _Address(self, version, command, addr, prefixlen, flags, scope, ifindex):
"""Adds or deletes an IP address."""
family = self._AddressFamily(version)
ifaddrmsg = IfAddrMsg((family, prefixlen, flags, scope, ifindex)).Pack()
ifaddrmsg += self._NlAttrIPAddress(IFA_ADDRESS, family, addr)
if version == 4:
ifaddrmsg += self._NlAttrIPAddress(IFA_LOCAL, family, addr)
- command = RTM_NEWADDR if is_add else RTM_DELADDR
self._SendNlRequest(command, ifaddrmsg)
def AddAddress(self, address, prefixlen, ifindex):
- version = 6 if ":" in address else 4
- return self._Address(version, True, address, prefixlen, IFA_F_PERMANENT,
- RT_SCOPE_UNIVERSE, ifindex)
+ self._Address(6 if ":" in address else 4,
+ RTM_NEWADDR, address, prefixlen,
+ IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, ifindex)
def DelAddress(self, address, prefixlen, ifindex):
- version = 6 if ":" in address else 4
- return self._Address(version, False, address, prefixlen, 0, 0, ifindex)
+ self._Address(6 if ":" in address else 4,
+ RTM_DELADDR, address, prefixlen, 0, 0, ifindex)
+
+ def GetAddress(self, address, ifindex=0):
+ if ":" not in address:
+ # The address is likely an IPv4 address. RTM_GETADDR without the
+ # NLM_F_DUMP flag is not supported by the kernel. We do not currently
+ # implement parsing dump results.
+ raise NotImplementedError("IPv4 RTM_GETADDR not implemented.")
+ self._Address(6, RTM_GETADDR, address, 0, 0, RT_SCOPE_UNIVERSE, ifindex)
+ data = self._Recv()
+ if NLMsgHdr(data).type == NLMSG_ERROR:
+ self._ParseAck(data)
+ return self._ParseNLMsg(data, IfAddrMsg)
def _Route(self, version, command, table, dest, prefixlen, nexthop, dev,
mark, uid):
@@ -492,7 +518,7 @@ class IPRoute(object):
version = 6 if ":" in dest else 4
prefixlen = {4: 32, 6: 128}[version]
self._Route(version, RTM_GETROUTE, 0, dest, prefixlen, None, oif, mark, uid)
- data = self. _Recv()
+ data = self._Recv()
# The response will either be an error or a list of routes.
if NLMsgHdr(data).type == NLMSG_ERROR:
self._ParseAck(data)
diff --git a/tests/net_test/mark_test.py b/tests/net_test/mark_test.py
index aa922fa8..2605246b 100755
--- a/tests/net_test/mark_test.py
+++ b/tests/net_test/mark_test.py
@@ -472,7 +472,7 @@ class MultiNetworkTest(net_test.NetworkTest):
#
# IPv6 uses autoconf for everything, except if per-device autoconf routing
# tables are not supported, in which case the default route (only) is
- # configured manually. For IPv4 we have to manualy configure addresses,
+ # configured manually. For IPv4 we have to manually configure addresses,
# routes, and neighbour cache entries (since we don't reply to ARP or ND).
#
# Since deleting addresses also causes routes to be deleted, we need to