xref: /aosp_15_r20/external/libnl/python/netlink/route/link.py (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker#
2*4dc78e53SAndroid Build Coastguard Worker# Copyright (c) 2011 Thomas Graf <[email protected]>
3*4dc78e53SAndroid Build Coastguard Worker#
4*4dc78e53SAndroid Build Coastguard Worker
5*4dc78e53SAndroid Build Coastguard Worker"""Module providing access to network links
6*4dc78e53SAndroid Build Coastguard Worker
7*4dc78e53SAndroid Build Coastguard WorkerThis module provides an interface to view configured network links,
8*4dc78e53SAndroid Build Coastguard Workermodify them and to add and delete virtual network links.
9*4dc78e53SAndroid Build Coastguard Worker
10*4dc78e53SAndroid Build Coastguard WorkerThe following is a basic example:
11*4dc78e53SAndroid Build Coastguard Worker    import netlink.core as netlink
12*4dc78e53SAndroid Build Coastguard Worker    import netlink.route.link as link
13*4dc78e53SAndroid Build Coastguard Worker
14*4dc78e53SAndroid Build Coastguard Worker    sock = netlink.Socket()
15*4dc78e53SAndroid Build Coastguard Worker    sock.connect(netlink.NETLINK_ROUTE)
16*4dc78e53SAndroid Build Coastguard Worker
17*4dc78e53SAndroid Build Coastguard Worker    cache = link.LinkCache()	# create new empty link cache
18*4dc78e53SAndroid Build Coastguard Worker    cache.refill(sock)		# fill cache with all configured links
19*4dc78e53SAndroid Build Coastguard Worker    eth0 = cache['eth0']		# lookup link "eth0"
20*4dc78e53SAndroid Build Coastguard Worker    print eth0			# print basic configuration
21*4dc78e53SAndroid Build Coastguard Worker
22*4dc78e53SAndroid Build Coastguard WorkerThe module contains the following public classes:
23*4dc78e53SAndroid Build Coastguard Worker
24*4dc78e53SAndroid Build Coastguard Worker  - Link -- Represents a network link. Instances can be created directly
25*4dc78e53SAndroid Build Coastguard Worker        via the constructor (empty link objects) or via the refill()
26*4dc78e53SAndroid Build Coastguard Worker        method of a LinkCache.
27*4dc78e53SAndroid Build Coastguard Worker  - LinkCache -- Derived from netlink.Cache, holds any number of
28*4dc78e53SAndroid Build Coastguard Worker         network links (Link instances). Main purpose is to keep
29*4dc78e53SAndroid Build Coastguard Worker         a local list of all network links configured in the
30*4dc78e53SAndroid Build Coastguard Worker         kernel.
31*4dc78e53SAndroid Build Coastguard Worker
32*4dc78e53SAndroid Build Coastguard WorkerThe following public functions exist:
33*4dc78e53SAndroid Build Coastguard Worker  - get_from_kernel(socket, name)
34*4dc78e53SAndroid Build Coastguard Worker
35*4dc78e53SAndroid Build Coastguard Worker"""
36*4dc78e53SAndroid Build Coastguard Worker
37*4dc78e53SAndroid Build Coastguard Workerfrom __future__ import absolute_import
38*4dc78e53SAndroid Build Coastguard Worker
39*4dc78e53SAndroid Build Coastguard Worker__version__ = "0.1"
40*4dc78e53SAndroid Build Coastguard Worker__all__ = [
41*4dc78e53SAndroid Build Coastguard Worker    "LinkCache",
42*4dc78e53SAndroid Build Coastguard Worker    "Link",
43*4dc78e53SAndroid Build Coastguard Worker]
44*4dc78e53SAndroid Build Coastguard Worker
45*4dc78e53SAndroid Build Coastguard Workerimport socket
46*4dc78e53SAndroid Build Coastguard Workerfrom .. import core as netlink
47*4dc78e53SAndroid Build Coastguard Workerfrom .. import capi as core_capi
48*4dc78e53SAndroid Build Coastguard Workerfrom . import capi as capi
49*4dc78e53SAndroid Build Coastguard Workerfrom .links import inet as inet
50*4dc78e53SAndroid Build Coastguard Workerfrom .. import util as util
51*4dc78e53SAndroid Build Coastguard Worker
52*4dc78e53SAndroid Build Coastguard Worker# Link statistics definitions
53*4dc78e53SAndroid Build Coastguard WorkerRX_PACKETS = 0
54*4dc78e53SAndroid Build Coastguard WorkerTX_PACKETS = 1
55*4dc78e53SAndroid Build Coastguard WorkerRX_BYTES = 2
56*4dc78e53SAndroid Build Coastguard WorkerTX_BYTES = 3
57*4dc78e53SAndroid Build Coastguard WorkerRX_ERRORS = 4
58*4dc78e53SAndroid Build Coastguard WorkerTX_ERRORS = 5
59*4dc78e53SAndroid Build Coastguard WorkerRX_DROPPED = 6
60*4dc78e53SAndroid Build Coastguard WorkerTX_DROPPED = 7
61*4dc78e53SAndroid Build Coastguard WorkerRX_COMPRESSED = 8
62*4dc78e53SAndroid Build Coastguard WorkerTX_COMPRESSED = 9
63*4dc78e53SAndroid Build Coastguard WorkerRX_FIFO_ERR = 10
64*4dc78e53SAndroid Build Coastguard WorkerTX_FIFO_ERR = 11
65*4dc78e53SAndroid Build Coastguard WorkerRX_LEN_ERR = 12
66*4dc78e53SAndroid Build Coastguard WorkerRX_OVER_ERR = 13
67*4dc78e53SAndroid Build Coastguard WorkerRX_CRC_ERR = 14
68*4dc78e53SAndroid Build Coastguard WorkerRX_FRAME_ERR = 15
69*4dc78e53SAndroid Build Coastguard WorkerRX_MISSED_ERR = 16
70*4dc78e53SAndroid Build Coastguard WorkerTX_ABORT_ERR = 17
71*4dc78e53SAndroid Build Coastguard WorkerTX_CARRIER_ERR = 18
72*4dc78e53SAndroid Build Coastguard WorkerTX_HBEAT_ERR = 19
73*4dc78e53SAndroid Build Coastguard WorkerTX_WIN_ERR = 20
74*4dc78e53SAndroid Build Coastguard WorkerCOLLISIONS = 21
75*4dc78e53SAndroid Build Coastguard WorkerMULTICAST = 22
76*4dc78e53SAndroid Build Coastguard WorkerIP6_INPKTS = 23
77*4dc78e53SAndroid Build Coastguard WorkerIP6_INHDRERRORS = 24
78*4dc78e53SAndroid Build Coastguard WorkerIP6_INTOOBIGERRORS = 25
79*4dc78e53SAndroid Build Coastguard WorkerIP6_INNOROUTES = 26
80*4dc78e53SAndroid Build Coastguard WorkerIP6_INADDRERRORS = 27
81*4dc78e53SAndroid Build Coastguard WorkerIP6_INUNKNOWNPROTOS = 28
82*4dc78e53SAndroid Build Coastguard WorkerIP6_INTRUNCATEDPKTS = 29
83*4dc78e53SAndroid Build Coastguard WorkerIP6_INDISCARDS = 30
84*4dc78e53SAndroid Build Coastguard WorkerIP6_INDELIVERS = 31
85*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTFORWDATAGRAMS = 32
86*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTPKTS = 33
87*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTDISCARDS = 34
88*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTNOROUTES = 35
89*4dc78e53SAndroid Build Coastguard WorkerIP6_REASMTIMEOUT = 36
90*4dc78e53SAndroid Build Coastguard WorkerIP6_REASMREQDS = 37
91*4dc78e53SAndroid Build Coastguard WorkerIP6_REASMOKS = 38
92*4dc78e53SAndroid Build Coastguard WorkerIP6_REASMFAILS = 39
93*4dc78e53SAndroid Build Coastguard WorkerIP6_FRAGOKS = 40
94*4dc78e53SAndroid Build Coastguard WorkerIP6_FRAGFAILS = 41
95*4dc78e53SAndroid Build Coastguard WorkerIP6_FRAGCREATES = 42
96*4dc78e53SAndroid Build Coastguard WorkerIP6_INMCASTPKTS = 43
97*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTMCASTPKTS = 44
98*4dc78e53SAndroid Build Coastguard WorkerIP6_INBCASTPKTS = 45
99*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTBCASTPKTS = 46
100*4dc78e53SAndroid Build Coastguard WorkerIP6_INOCTETS = 47
101*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTOCTETS = 48
102*4dc78e53SAndroid Build Coastguard WorkerIP6_INMCASTOCTETS = 49
103*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTMCASTOCTETS = 50
104*4dc78e53SAndroid Build Coastguard WorkerIP6_INBCASTOCTETS = 51
105*4dc78e53SAndroid Build Coastguard WorkerIP6_OUTBCASTOCTETS = 52
106*4dc78e53SAndroid Build Coastguard WorkerICMP6_INMSGS = 53
107*4dc78e53SAndroid Build Coastguard WorkerICMP6_INERRORS = 54
108*4dc78e53SAndroid Build Coastguard WorkerICMP6_OUTMSGS = 55
109*4dc78e53SAndroid Build Coastguard WorkerICMP6_OUTERRORS = 56
110*4dc78e53SAndroid Build Coastguard Worker
111*4dc78e53SAndroid Build Coastguard Worker
112*4dc78e53SAndroid Build Coastguard Workerclass LinkCache(netlink.Cache):
113*4dc78e53SAndroid Build Coastguard Worker    """Cache of network links"""
114*4dc78e53SAndroid Build Coastguard Worker
115*4dc78e53SAndroid Build Coastguard Worker    def __init__(self, family=socket.AF_UNSPEC, cache=None):
116*4dc78e53SAndroid Build Coastguard Worker        if not cache:
117*4dc78e53SAndroid Build Coastguard Worker            cache = self._alloc_cache_name("route/link")
118*4dc78e53SAndroid Build Coastguard Worker
119*4dc78e53SAndroid Build Coastguard Worker        self._info_module = None
120*4dc78e53SAndroid Build Coastguard Worker        self._protocol = netlink.NETLINK_ROUTE
121*4dc78e53SAndroid Build Coastguard Worker        self._nl_cache = cache
122*4dc78e53SAndroid Build Coastguard Worker        self._set_arg1(family)
123*4dc78e53SAndroid Build Coastguard Worker
124*4dc78e53SAndroid Build Coastguard Worker    def __getitem__(self, key):
125*4dc78e53SAndroid Build Coastguard Worker        if type(key) is int:
126*4dc78e53SAndroid Build Coastguard Worker            link = capi.rtnl_link_get(self._nl_cache, key)
127*4dc78e53SAndroid Build Coastguard Worker        else:
128*4dc78e53SAndroid Build Coastguard Worker            link = capi.rtnl_link_get_by_name(self._nl_cache, key)
129*4dc78e53SAndroid Build Coastguard Worker
130*4dc78e53SAndroid Build Coastguard Worker        if link is None:
131*4dc78e53SAndroid Build Coastguard Worker            raise KeyError()
132*4dc78e53SAndroid Build Coastguard Worker        else:
133*4dc78e53SAndroid Build Coastguard Worker            return Link.from_capi(link)
134*4dc78e53SAndroid Build Coastguard Worker
135*4dc78e53SAndroid Build Coastguard Worker    @staticmethod
136*4dc78e53SAndroid Build Coastguard Worker    def _new_object(obj):
137*4dc78e53SAndroid Build Coastguard Worker        return Link(obj)
138*4dc78e53SAndroid Build Coastguard Worker
139*4dc78e53SAndroid Build Coastguard Worker    def _new_cache(self, cache):
140*4dc78e53SAndroid Build Coastguard Worker        return LinkCache(family=self.arg1, cache=cache)
141*4dc78e53SAndroid Build Coastguard Worker
142*4dc78e53SAndroid Build Coastguard Worker
143*4dc78e53SAndroid Build Coastguard Workerclass Link(netlink.Object):
144*4dc78e53SAndroid Build Coastguard Worker    """Network link"""
145*4dc78e53SAndroid Build Coastguard Worker
146*4dc78e53SAndroid Build Coastguard Worker    def __init__(self, obj=None):
147*4dc78e53SAndroid Build Coastguard Worker        netlink.Object.__init__(self, "route/link", "link", obj)
148*4dc78e53SAndroid Build Coastguard Worker        self._rtnl_link = self._obj2type(self._nl_object)
149*4dc78e53SAndroid Build Coastguard Worker
150*4dc78e53SAndroid Build Coastguard Worker        if self.type:
151*4dc78e53SAndroid Build Coastguard Worker            self._module_lookup("netlink.route.links." + self.type)
152*4dc78e53SAndroid Build Coastguard Worker
153*4dc78e53SAndroid Build Coastguard Worker        self.inet = inet.InetLink(self)
154*4dc78e53SAndroid Build Coastguard Worker        self.af = {"inet": self.inet}
155*4dc78e53SAndroid Build Coastguard Worker
156*4dc78e53SAndroid Build Coastguard Worker    def __enter__(self):
157*4dc78e53SAndroid Build Coastguard Worker        return self
158*4dc78e53SAndroid Build Coastguard Worker
159*4dc78e53SAndroid Build Coastguard Worker    def __exit__(self, exc_type, exc_value, tb):
160*4dc78e53SAndroid Build Coastguard Worker        if exc_type is None:
161*4dc78e53SAndroid Build Coastguard Worker            self.change()
162*4dc78e53SAndroid Build Coastguard Worker        else:
163*4dc78e53SAndroid Build Coastguard Worker            return False
164*4dc78e53SAndroid Build Coastguard Worker
165*4dc78e53SAndroid Build Coastguard Worker    @classmethod
166*4dc78e53SAndroid Build Coastguard Worker    def from_capi(cls, obj):
167*4dc78e53SAndroid Build Coastguard Worker        return cls(capi.link2obj(obj))
168*4dc78e53SAndroid Build Coastguard Worker
169*4dc78e53SAndroid Build Coastguard Worker    @staticmethod
170*4dc78e53SAndroid Build Coastguard Worker    def _obj2type(obj):
171*4dc78e53SAndroid Build Coastguard Worker        return capi.obj2link(obj)
172*4dc78e53SAndroid Build Coastguard Worker
173*4dc78e53SAndroid Build Coastguard Worker    def __cmp__(self, other):
174*4dc78e53SAndroid Build Coastguard Worker        return self.ifindex - other.ifindex
175*4dc78e53SAndroid Build Coastguard Worker
176*4dc78e53SAndroid Build Coastguard Worker    @staticmethod
177*4dc78e53SAndroid Build Coastguard Worker    def _new_instance(obj):
178*4dc78e53SAndroid Build Coastguard Worker        if not obj:
179*4dc78e53SAndroid Build Coastguard Worker            raise ValueError()
180*4dc78e53SAndroid Build Coastguard Worker
181*4dc78e53SAndroid Build Coastguard Worker        return Link(obj)
182*4dc78e53SAndroid Build Coastguard Worker
183*4dc78e53SAndroid Build Coastguard Worker    @property
184*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=int, immutable=True, fmt=util.num)
185*4dc78e53SAndroid Build Coastguard Worker    def ifindex(self):
186*4dc78e53SAndroid Build Coastguard Worker        """interface index"""
187*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_ifindex(self._rtnl_link)
188*4dc78e53SAndroid Build Coastguard Worker
189*4dc78e53SAndroid Build Coastguard Worker    @ifindex.setter
190*4dc78e53SAndroid Build Coastguard Worker    def ifindex(self, value):
191*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_ifindex(self._rtnl_link, int(value))
192*4dc78e53SAndroid Build Coastguard Worker
193*4dc78e53SAndroid Build Coastguard Worker        # ifindex is immutable but we assume that if _orig does not
194*4dc78e53SAndroid Build Coastguard Worker        # have an ifindex specified, it was meant to be given here
195*4dc78e53SAndroid Build Coastguard Worker        if capi.rtnl_link_get_ifindex(self._orig) == 0:
196*4dc78e53SAndroid Build Coastguard Worker            capi.rtnl_link_set_ifindex(self._orig, int(value))
197*4dc78e53SAndroid Build Coastguard Worker
198*4dc78e53SAndroid Build Coastguard Worker    @property
199*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.bold)
200*4dc78e53SAndroid Build Coastguard Worker    def name(self):
201*4dc78e53SAndroid Build Coastguard Worker        """Name of link"""
202*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_name(self._rtnl_link)
203*4dc78e53SAndroid Build Coastguard Worker
204*4dc78e53SAndroid Build Coastguard Worker    @name.setter
205*4dc78e53SAndroid Build Coastguard Worker    def name(self, value):
206*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_name(self._rtnl_link, value)
207*4dc78e53SAndroid Build Coastguard Worker
208*4dc78e53SAndroid Build Coastguard Worker        # name is the secondary identifier, if _orig does not have
209*4dc78e53SAndroid Build Coastguard Worker        # the name specified yet, assume it was meant to be specified
210*4dc78e53SAndroid Build Coastguard Worker        # here. ifindex will always take priority, therefore if ifindex
211*4dc78e53SAndroid Build Coastguard Worker        # is specified as well, this will be ignored automatically.
212*4dc78e53SAndroid Build Coastguard Worker        if capi.rtnl_link_get_name(self._orig) is None:
213*4dc78e53SAndroid Build Coastguard Worker            capi.rtnl_link_set_name(self._orig, value)
214*4dc78e53SAndroid Build Coastguard Worker
215*4dc78e53SAndroid Build Coastguard Worker    @property
216*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.string)
217*4dc78e53SAndroid Build Coastguard Worker    def flags(self):
218*4dc78e53SAndroid Build Coastguard Worker        """Flags
219*4dc78e53SAndroid Build Coastguard Worker        Setting this property will *Not* reset flags to value you supply in
220*4dc78e53SAndroid Build Coastguard Worker        Examples:
221*4dc78e53SAndroid Build Coastguard Worker        link.flags = '+xxx' # add xxx flag
222*4dc78e53SAndroid Build Coastguard Worker        link.flags = 'xxx'  # exactly the same
223*4dc78e53SAndroid Build Coastguard Worker        link.flags = '-xxx' # remove xxx flag
224*4dc78e53SAndroid Build Coastguard Worker        link.flags = [ '+xxx', '-yyy' ] # list operation
225*4dc78e53SAndroid Build Coastguard Worker        """
226*4dc78e53SAndroid Build Coastguard Worker        flags = capi.rtnl_link_get_flags(self._rtnl_link)
227*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_flags2str(flags, 256)[0].split(",")
228*4dc78e53SAndroid Build Coastguard Worker
229*4dc78e53SAndroid Build Coastguard Worker    def _set_flag(self, flag):
230*4dc78e53SAndroid Build Coastguard Worker        if flag.startswith("-"):
231*4dc78e53SAndroid Build Coastguard Worker            i = capi.rtnl_link_str2flags(flag[1:])
232*4dc78e53SAndroid Build Coastguard Worker            capi.rtnl_link_unset_flags(self._rtnl_link, i)
233*4dc78e53SAndroid Build Coastguard Worker        elif flag.startswith("+"):
234*4dc78e53SAndroid Build Coastguard Worker            i = capi.rtnl_link_str2flags(flag[1:])
235*4dc78e53SAndroid Build Coastguard Worker            capi.rtnl_link_set_flags(self._rtnl_link, i)
236*4dc78e53SAndroid Build Coastguard Worker        else:
237*4dc78e53SAndroid Build Coastguard Worker            i = capi.rtnl_link_str2flags(flag)
238*4dc78e53SAndroid Build Coastguard Worker            capi.rtnl_link_set_flags(self._rtnl_link, i)
239*4dc78e53SAndroid Build Coastguard Worker
240*4dc78e53SAndroid Build Coastguard Worker    @flags.setter
241*4dc78e53SAndroid Build Coastguard Worker    def flags(self, value):
242*4dc78e53SAndroid Build Coastguard Worker        if not (type(value) is str):
243*4dc78e53SAndroid Build Coastguard Worker            for flag in value:
244*4dc78e53SAndroid Build Coastguard Worker                self._set_flag(flag)
245*4dc78e53SAndroid Build Coastguard Worker        else:
246*4dc78e53SAndroid Build Coastguard Worker            self._set_flag(value)
247*4dc78e53SAndroid Build Coastguard Worker
248*4dc78e53SAndroid Build Coastguard Worker    @property
249*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=int, fmt=util.num)
250*4dc78e53SAndroid Build Coastguard Worker    def mtu(self):
251*4dc78e53SAndroid Build Coastguard Worker        """Maximum Transmission Unit"""
252*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_mtu(self._rtnl_link)
253*4dc78e53SAndroid Build Coastguard Worker
254*4dc78e53SAndroid Build Coastguard Worker    @mtu.setter
255*4dc78e53SAndroid Build Coastguard Worker    def mtu(self, value):
256*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_mtu(self._rtnl_link, int(value))
257*4dc78e53SAndroid Build Coastguard Worker
258*4dc78e53SAndroid Build Coastguard Worker    @property
259*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=int, immutable=True, fmt=util.num)
260*4dc78e53SAndroid Build Coastguard Worker    def family(self):
261*4dc78e53SAndroid Build Coastguard Worker        """Address family"""
262*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_family(self._rtnl_link)
263*4dc78e53SAndroid Build Coastguard Worker
264*4dc78e53SAndroid Build Coastguard Worker    @family.setter
265*4dc78e53SAndroid Build Coastguard Worker    def family(self, value):
266*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_family(self._rtnl_link, value)
267*4dc78e53SAndroid Build Coastguard Worker
268*4dc78e53SAndroid Build Coastguard Worker    @property
269*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.addr)
270*4dc78e53SAndroid Build Coastguard Worker    def address(self):
271*4dc78e53SAndroid Build Coastguard Worker        """Hardware address (MAC address)"""
272*4dc78e53SAndroid Build Coastguard Worker        a = capi.rtnl_link_get_addr(self._rtnl_link)
273*4dc78e53SAndroid Build Coastguard Worker        return netlink.AbstractAddress(a)
274*4dc78e53SAndroid Build Coastguard Worker
275*4dc78e53SAndroid Build Coastguard Worker    @address.setter
276*4dc78e53SAndroid Build Coastguard Worker    def address(self, value):
277*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_addr(self._rtnl_link, value._addr)
278*4dc78e53SAndroid Build Coastguard Worker
279*4dc78e53SAndroid Build Coastguard Worker    @property
280*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.addr)
281*4dc78e53SAndroid Build Coastguard Worker    def broadcast(self):
282*4dc78e53SAndroid Build Coastguard Worker        """Hardware broadcast address"""
283*4dc78e53SAndroid Build Coastguard Worker        a = capi.rtnl_link_get_broadcast(self._rtnl_link)
284*4dc78e53SAndroid Build Coastguard Worker        return netlink.AbstractAddress(a)
285*4dc78e53SAndroid Build Coastguard Worker
286*4dc78e53SAndroid Build Coastguard Worker    @broadcast.setter
287*4dc78e53SAndroid Build Coastguard Worker    def broadcast(self, value):
288*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr)
289*4dc78e53SAndroid Build Coastguard Worker
290*4dc78e53SAndroid Build Coastguard Worker    @property
291*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, immutable=True, fmt=util.string)
292*4dc78e53SAndroid Build Coastguard Worker    def qdisc(self):
293*4dc78e53SAndroid Build Coastguard Worker        """Name of qdisc (cannot be changed)"""
294*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_qdisc(self._rtnl_link)
295*4dc78e53SAndroid Build Coastguard Worker
296*4dc78e53SAndroid Build Coastguard Worker    @qdisc.setter
297*4dc78e53SAndroid Build Coastguard Worker    def qdisc(self, value):
298*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_qdisc(self._rtnl_link, value)
299*4dc78e53SAndroid Build Coastguard Worker
300*4dc78e53SAndroid Build Coastguard Worker    @property
301*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=int, fmt=util.num)
302*4dc78e53SAndroid Build Coastguard Worker    def txqlen(self):
303*4dc78e53SAndroid Build Coastguard Worker        """Length of transmit queue"""
304*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_txqlen(self._rtnl_link)
305*4dc78e53SAndroid Build Coastguard Worker
306*4dc78e53SAndroid Build Coastguard Worker    @txqlen.setter
307*4dc78e53SAndroid Build Coastguard Worker    def txqlen(self, value):
308*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_txqlen(self._rtnl_link, int(value))
309*4dc78e53SAndroid Build Coastguard Worker
310*4dc78e53SAndroid Build Coastguard Worker    @property
311*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, immutable=True, fmt=util.string)
312*4dc78e53SAndroid Build Coastguard Worker    def arptype(self):
313*4dc78e53SAndroid Build Coastguard Worker        """Type of link (cannot be changed)"""
314*4dc78e53SAndroid Build Coastguard Worker        type_ = capi.rtnl_link_get_arptype(self._rtnl_link)
315*4dc78e53SAndroid Build Coastguard Worker        return core_capi.nl_llproto2str(type_, 64)[0]
316*4dc78e53SAndroid Build Coastguard Worker
317*4dc78e53SAndroid Build Coastguard Worker    @arptype.setter
318*4dc78e53SAndroid Build Coastguard Worker    def arptype(self, value):
319*4dc78e53SAndroid Build Coastguard Worker        i = core_capi.nl_str2llproto(value)
320*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_arptype(self._rtnl_link, i)
321*4dc78e53SAndroid Build Coastguard Worker
322*4dc78e53SAndroid Build Coastguard Worker    @property
323*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, immutable=True, fmt=util.string, title="state")
324*4dc78e53SAndroid Build Coastguard Worker    def operstate(self):
325*4dc78e53SAndroid Build Coastguard Worker        """Operational status"""
326*4dc78e53SAndroid Build Coastguard Worker        operstate = capi.rtnl_link_get_operstate(self._rtnl_link)
327*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_operstate2str(operstate, 32)[0]
328*4dc78e53SAndroid Build Coastguard Worker
329*4dc78e53SAndroid Build Coastguard Worker    @operstate.setter
330*4dc78e53SAndroid Build Coastguard Worker    def operstate(self, value):
331*4dc78e53SAndroid Build Coastguard Worker        i = capi.rtnl_link_str2operstate(value)
332*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_operstate(self._rtnl_link, i)
333*4dc78e53SAndroid Build Coastguard Worker
334*4dc78e53SAndroid Build Coastguard Worker    @property
335*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, immutable=True, fmt=util.string)
336*4dc78e53SAndroid Build Coastguard Worker    def mode(self):
337*4dc78e53SAndroid Build Coastguard Worker        """Link mode"""
338*4dc78e53SAndroid Build Coastguard Worker        mode = capi.rtnl_link_get_linkmode(self._rtnl_link)
339*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_mode2str(mode, 32)[0]
340*4dc78e53SAndroid Build Coastguard Worker
341*4dc78e53SAndroid Build Coastguard Worker    @mode.setter
342*4dc78e53SAndroid Build Coastguard Worker    def mode(self, value):
343*4dc78e53SAndroid Build Coastguard Worker        i = capi.rtnl_link_str2mode(value)
344*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_linkmode(self._rtnl_link, i)
345*4dc78e53SAndroid Build Coastguard Worker
346*4dc78e53SAndroid Build Coastguard Worker    @property
347*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.string)
348*4dc78e53SAndroid Build Coastguard Worker    def alias(self):
349*4dc78e53SAndroid Build Coastguard Worker        """Interface alias (SNMP)"""
350*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_ifalias(self._rtnl_link)
351*4dc78e53SAndroid Build Coastguard Worker
352*4dc78e53SAndroid Build Coastguard Worker    @alias.setter
353*4dc78e53SAndroid Build Coastguard Worker    def alias(self, value):
354*4dc78e53SAndroid Build Coastguard Worker        capi.rtnl_link_set_ifalias(self._rtnl_link, value)
355*4dc78e53SAndroid Build Coastguard Worker
356*4dc78e53SAndroid Build Coastguard Worker    @property
357*4dc78e53SAndroid Build Coastguard Worker    @netlink.nlattr(type=str, fmt=util.string)
358*4dc78e53SAndroid Build Coastguard Worker    def type(self):
359*4dc78e53SAndroid Build Coastguard Worker        """Link type"""
360*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_type(self._rtnl_link)
361*4dc78e53SAndroid Build Coastguard Worker
362*4dc78e53SAndroid Build Coastguard Worker    @type.setter
363*4dc78e53SAndroid Build Coastguard Worker    def type(self, value):
364*4dc78e53SAndroid Build Coastguard Worker        if capi.rtnl_link_set_type(self._rtnl_link, value) < 0:
365*4dc78e53SAndroid Build Coastguard Worker            raise NameError("unknown info type")
366*4dc78e53SAndroid Build Coastguard Worker
367*4dc78e53SAndroid Build Coastguard Worker        self._module_lookup("netlink.route.links." + value)
368*4dc78e53SAndroid Build Coastguard Worker
369*4dc78e53SAndroid Build Coastguard Worker    def get_stat(self, stat):
370*4dc78e53SAndroid Build Coastguard Worker        """Retrieve statistical information"""
371*4dc78e53SAndroid Build Coastguard Worker        if type(stat) is str:
372*4dc78e53SAndroid Build Coastguard Worker            stat = capi.rtnl_link_str2stat(stat)
373*4dc78e53SAndroid Build Coastguard Worker            if stat < 0:
374*4dc78e53SAndroid Build Coastguard Worker                raise NameError("unknown name of statistic")
375*4dc78e53SAndroid Build Coastguard Worker
376*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_get_stat(self._rtnl_link, stat)
377*4dc78e53SAndroid Build Coastguard Worker
378*4dc78e53SAndroid Build Coastguard Worker    def enslave(self, slave, sock=None):
379*4dc78e53SAndroid Build Coastguard Worker        if not sock:
380*4dc78e53SAndroid Build Coastguard Worker            sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
381*4dc78e53SAndroid Build Coastguard Worker
382*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_enslave(sock._sock, self._rtnl_link, slave._rtnl_link)
383*4dc78e53SAndroid Build Coastguard Worker
384*4dc78e53SAndroid Build Coastguard Worker    def release(self, slave, sock=None):
385*4dc78e53SAndroid Build Coastguard Worker        if not sock:
386*4dc78e53SAndroid Build Coastguard Worker            sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
387*4dc78e53SAndroid Build Coastguard Worker
388*4dc78e53SAndroid Build Coastguard Worker        return capi.rtnl_link_release(sock._sock, self._rtnl_link, slave._rtnl_link)
389*4dc78e53SAndroid Build Coastguard Worker
390*4dc78e53SAndroid Build Coastguard Worker    def add(self, sock=None, flags=None):
391*4dc78e53SAndroid Build Coastguard Worker        if not sock:
392*4dc78e53SAndroid Build Coastguard Worker            sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
393*4dc78e53SAndroid Build Coastguard Worker
394*4dc78e53SAndroid Build Coastguard Worker        if not flags:
395*4dc78e53SAndroid Build Coastguard Worker            flags = netlink.NLM_F_CREATE
396*4dc78e53SAndroid Build Coastguard Worker
397*4dc78e53SAndroid Build Coastguard Worker        ret = capi.rtnl_link_add(sock._sock, self._rtnl_link, flags)
398*4dc78e53SAndroid Build Coastguard Worker        if ret < 0:
399*4dc78e53SAndroid Build Coastguard Worker            raise netlink.KernelError(ret)
400*4dc78e53SAndroid Build Coastguard Worker
401*4dc78e53SAndroid Build Coastguard Worker    def change(self, sock=None, flags=0):
402*4dc78e53SAndroid Build Coastguard Worker        """Commit changes made to the link object"""
403*4dc78e53SAndroid Build Coastguard Worker        if sock is None:
404*4dc78e53SAndroid Build Coastguard Worker            sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
405*4dc78e53SAndroid Build Coastguard Worker
406*4dc78e53SAndroid Build Coastguard Worker        if not self._orig:
407*4dc78e53SAndroid Build Coastguard Worker            raise netlink.NetlinkError("Original link not available")
408*4dc78e53SAndroid Build Coastguard Worker        ret = capi.rtnl_link_change(sock._sock, self._orig, self._rtnl_link, flags)
409*4dc78e53SAndroid Build Coastguard Worker        if ret < 0:
410*4dc78e53SAndroid Build Coastguard Worker            raise netlink.KernelError(ret)
411*4dc78e53SAndroid Build Coastguard Worker
412*4dc78e53SAndroid Build Coastguard Worker    def delete(self, sock=None):
413*4dc78e53SAndroid Build Coastguard Worker        """Attempt to delete this link in the kernel"""
414*4dc78e53SAndroid Build Coastguard Worker        if sock is None:
415*4dc78e53SAndroid Build Coastguard Worker            sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
416*4dc78e53SAndroid Build Coastguard Worker
417*4dc78e53SAndroid Build Coastguard Worker        ret = capi.rtnl_link_delete(sock._sock, self._rtnl_link)
418*4dc78e53SAndroid Build Coastguard Worker        if ret < 0:
419*4dc78e53SAndroid Build Coastguard Worker            raise netlink.KernelError(ret)
420*4dc78e53SAndroid Build Coastguard Worker
421*4dc78e53SAndroid Build Coastguard Worker    ###################################################################
422*4dc78e53SAndroid Build Coastguard Worker    # private properties
423*4dc78e53SAndroid Build Coastguard Worker    #
424*4dc78e53SAndroid Build Coastguard Worker    # Used for formatting output. USE AT OWN RISK
425*4dc78e53SAndroid Build Coastguard Worker    @property
426*4dc78e53SAndroid Build Coastguard Worker    def _state(self):
427*4dc78e53SAndroid Build Coastguard Worker        if "up" in self.flags:
428*4dc78e53SAndroid Build Coastguard Worker            buf = util.good("up")
429*4dc78e53SAndroid Build Coastguard Worker            if "lowerup" not in self.flags:
430*4dc78e53SAndroid Build Coastguard Worker                buf += " " + util.bad("no-carrier")
431*4dc78e53SAndroid Build Coastguard Worker        else:
432*4dc78e53SAndroid Build Coastguard Worker            buf = util.bad("down")
433*4dc78e53SAndroid Build Coastguard Worker        return buf
434*4dc78e53SAndroid Build Coastguard Worker
435*4dc78e53SAndroid Build Coastguard Worker    @property
436*4dc78e53SAndroid Build Coastguard Worker    def _brief(self):
437*4dc78e53SAndroid Build Coastguard Worker        return self._module_brief() + self._foreach_af("brief")
438*4dc78e53SAndroid Build Coastguard Worker
439*4dc78e53SAndroid Build Coastguard Worker    @property
440*4dc78e53SAndroid Build Coastguard Worker    def _flags(self):
441*4dc78e53SAndroid Build Coastguard Worker        ignore = [
442*4dc78e53SAndroid Build Coastguard Worker            "up",
443*4dc78e53SAndroid Build Coastguard Worker            "running",
444*4dc78e53SAndroid Build Coastguard Worker            "lowerup",
445*4dc78e53SAndroid Build Coastguard Worker        ]
446*4dc78e53SAndroid Build Coastguard Worker        return ",".join([flag for flag in self.flags if flag not in ignore])
447*4dc78e53SAndroid Build Coastguard Worker
448*4dc78e53SAndroid Build Coastguard Worker    def _foreach_af(self, name, args=None):
449*4dc78e53SAndroid Build Coastguard Worker        buf = ""
450*4dc78e53SAndroid Build Coastguard Worker        for af in self.af:
451*4dc78e53SAndroid Build Coastguard Worker            try:
452*4dc78e53SAndroid Build Coastguard Worker                func = getattr(self.af[af], name)
453*4dc78e53SAndroid Build Coastguard Worker                s = str(func(args))
454*4dc78e53SAndroid Build Coastguard Worker                if len(s) > 0:
455*4dc78e53SAndroid Build Coastguard Worker                    buf += " " + s
456*4dc78e53SAndroid Build Coastguard Worker            except AttributeError:
457*4dc78e53SAndroid Build Coastguard Worker                pass
458*4dc78e53SAndroid Build Coastguard Worker        return buf
459*4dc78e53SAndroid Build Coastguard Worker
460*4dc78e53SAndroid Build Coastguard Worker    def format(self, details=False, stats=False, indent=""):
461*4dc78e53SAndroid Build Coastguard Worker        """Return link as formatted text"""
462*4dc78e53SAndroid Build Coastguard Worker        fmt = util.MyFormatter(self, indent)
463*4dc78e53SAndroid Build Coastguard Worker
464*4dc78e53SAndroid Build Coastguard Worker        buf = fmt.format(
465*4dc78e53SAndroid Build Coastguard Worker            "{a|ifindex} {a|name} {a|arptype} {a|address} "
466*4dc78e53SAndroid Build Coastguard Worker            "{a|_state} <{a|_flags}> {a|_brief}"
467*4dc78e53SAndroid Build Coastguard Worker        )
468*4dc78e53SAndroid Build Coastguard Worker
469*4dc78e53SAndroid Build Coastguard Worker        if details:
470*4dc78e53SAndroid Build Coastguard Worker            buf += fmt.nl("\t{t|mtu} {t|txqlen} {t|weight} " "{t|qdisc} {t|operstate}")
471*4dc78e53SAndroid Build Coastguard Worker            buf += fmt.nl("\t{t|broadcast} {t|alias}")
472*4dc78e53SAndroid Build Coastguard Worker
473*4dc78e53SAndroid Build Coastguard Worker            buf += self._foreach_af("details", fmt)
474*4dc78e53SAndroid Build Coastguard Worker
475*4dc78e53SAndroid Build Coastguard Worker        if stats:
476*4dc78e53SAndroid Build Coastguard Worker            lst = [
477*4dc78e53SAndroid Build Coastguard Worker                ["Packets", RX_PACKETS, TX_PACKETS],
478*4dc78e53SAndroid Build Coastguard Worker                ["Bytes", RX_BYTES, TX_BYTES],
479*4dc78e53SAndroid Build Coastguard Worker                ["Errors", RX_ERRORS, TX_ERRORS],
480*4dc78e53SAndroid Build Coastguard Worker                ["Dropped", RX_DROPPED, TX_DROPPED],
481*4dc78e53SAndroid Build Coastguard Worker                ["Compressed", RX_COMPRESSED, TX_COMPRESSED],
482*4dc78e53SAndroid Build Coastguard Worker                ["FIFO Errors", RX_FIFO_ERR, TX_FIFO_ERR],
483*4dc78e53SAndroid Build Coastguard Worker                ["Length Errors", RX_LEN_ERR, None],
484*4dc78e53SAndroid Build Coastguard Worker                ["Over Errors", RX_OVER_ERR, None],
485*4dc78e53SAndroid Build Coastguard Worker                ["CRC Errors", RX_CRC_ERR, None],
486*4dc78e53SAndroid Build Coastguard Worker                ["Frame Errors", RX_FRAME_ERR, None],
487*4dc78e53SAndroid Build Coastguard Worker                ["Missed Errors", RX_MISSED_ERR, None],
488*4dc78e53SAndroid Build Coastguard Worker                ["Abort Errors", None, TX_ABORT_ERR],
489*4dc78e53SAndroid Build Coastguard Worker                ["Carrier Errors", None, TX_CARRIER_ERR],
490*4dc78e53SAndroid Build Coastguard Worker                ["Heartbeat Errors", None, TX_HBEAT_ERR],
491*4dc78e53SAndroid Build Coastguard Worker                ["Window Errors", None, TX_WIN_ERR],
492*4dc78e53SAndroid Build Coastguard Worker                ["Collisions", None, COLLISIONS],
493*4dc78e53SAndroid Build Coastguard Worker                ["Multicast", None, MULTICAST],
494*4dc78e53SAndroid Build Coastguard Worker                ["", None, None],
495*4dc78e53SAndroid Build Coastguard Worker                ["Ipv6:", None, None],
496*4dc78e53SAndroid Build Coastguard Worker                ["Packets", IP6_INPKTS, IP6_OUTPKTS],
497*4dc78e53SAndroid Build Coastguard Worker                ["Bytes", IP6_INOCTETS, IP6_OUTOCTETS],
498*4dc78e53SAndroid Build Coastguard Worker                ["Discards", IP6_INDISCARDS, IP6_OUTDISCARDS],
499*4dc78e53SAndroid Build Coastguard Worker                ["Multicast Packets", IP6_INMCASTPKTS, IP6_OUTMCASTPKTS],
500*4dc78e53SAndroid Build Coastguard Worker                ["Multicast Bytes", IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS],
501*4dc78e53SAndroid Build Coastguard Worker                ["Broadcast Packets", IP6_INBCASTPKTS, IP6_OUTBCASTPKTS],
502*4dc78e53SAndroid Build Coastguard Worker                ["Broadcast Bytes", IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS],
503*4dc78e53SAndroid Build Coastguard Worker                ["Delivers", IP6_INDELIVERS, None],
504*4dc78e53SAndroid Build Coastguard Worker                ["Forwarded", None, IP6_OUTFORWDATAGRAMS],
505*4dc78e53SAndroid Build Coastguard Worker                ["No Routes", IP6_INNOROUTES, IP6_OUTNOROUTES],
506*4dc78e53SAndroid Build Coastguard Worker                ["Header Errors", IP6_INHDRERRORS, None],
507*4dc78e53SAndroid Build Coastguard Worker                ["Too Big Errors", IP6_INTOOBIGERRORS, None],
508*4dc78e53SAndroid Build Coastguard Worker                ["Address Errors", IP6_INADDRERRORS, None],
509*4dc78e53SAndroid Build Coastguard Worker                ["Unknown Protocol", IP6_INUNKNOWNPROTOS, None],
510*4dc78e53SAndroid Build Coastguard Worker                ["Truncated Packets", IP6_INTRUNCATEDPKTS, None],
511*4dc78e53SAndroid Build Coastguard Worker                ["Reasm Timeouts", IP6_REASMTIMEOUT, None],
512*4dc78e53SAndroid Build Coastguard Worker                ["Reasm Requests", IP6_REASMREQDS, None],
513*4dc78e53SAndroid Build Coastguard Worker                ["Reasm Failures", IP6_REASMFAILS, None],
514*4dc78e53SAndroid Build Coastguard Worker                ["Reasm OK", IP6_REASMOKS, None],
515*4dc78e53SAndroid Build Coastguard Worker                ["Frag Created", None, IP6_FRAGCREATES],
516*4dc78e53SAndroid Build Coastguard Worker                ["Frag Failures", None, IP6_FRAGFAILS],
517*4dc78e53SAndroid Build Coastguard Worker                ["Frag OK", None, IP6_FRAGOKS],
518*4dc78e53SAndroid Build Coastguard Worker                ["", None, None],
519*4dc78e53SAndroid Build Coastguard Worker                ["ICMPv6:", None, None],
520*4dc78e53SAndroid Build Coastguard Worker                ["Messages", ICMP6_INMSGS, ICMP6_OUTMSGS],
521*4dc78e53SAndroid Build Coastguard Worker                ["Errors", ICMP6_INERRORS, ICMP6_OUTERRORS],
522*4dc78e53SAndroid Build Coastguard Worker            ]
523*4dc78e53SAndroid Build Coastguard Worker
524*4dc78e53SAndroid Build Coastguard Worker            buf += "\n\t%s%s%s%s\n" % (
525*4dc78e53SAndroid Build Coastguard Worker                33 * " ",
526*4dc78e53SAndroid Build Coastguard Worker                util.title("RX"),
527*4dc78e53SAndroid Build Coastguard Worker                15 * " ",
528*4dc78e53SAndroid Build Coastguard Worker                util.title("TX"),
529*4dc78e53SAndroid Build Coastguard Worker            )
530*4dc78e53SAndroid Build Coastguard Worker
531*4dc78e53SAndroid Build Coastguard Worker            for row in lst:
532*4dc78e53SAndroid Build Coastguard Worker                row[0] = util.kw(row[0])
533*4dc78e53SAndroid Build Coastguard Worker                row[1] = self.get_stat(row[1]) if row[1] else ""
534*4dc78e53SAndroid Build Coastguard Worker                row[2] = self.get_stat(row[2]) if row[2] else ""
535*4dc78e53SAndroid Build Coastguard Worker                buf += "\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n".format(row)
536*4dc78e53SAndroid Build Coastguard Worker
537*4dc78e53SAndroid Build Coastguard Worker            buf += self._foreach_af("stats")
538*4dc78e53SAndroid Build Coastguard Worker
539*4dc78e53SAndroid Build Coastguard Worker        return buf
540*4dc78e53SAndroid Build Coastguard Worker
541*4dc78e53SAndroid Build Coastguard Worker
542*4dc78e53SAndroid Build Coastguard Workerdef get(name, sock=None):
543*4dc78e53SAndroid Build Coastguard Worker    """Lookup Link object directly from kernel"""
544*4dc78e53SAndroid Build Coastguard Worker    if not name:
545*4dc78e53SAndroid Build Coastguard Worker        raise ValueError()
546*4dc78e53SAndroid Build Coastguard Worker
547*4dc78e53SAndroid Build Coastguard Worker    if not sock:
548*4dc78e53SAndroid Build Coastguard Worker        sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
549*4dc78e53SAndroid Build Coastguard Worker
550*4dc78e53SAndroid Build Coastguard Worker    link = capi.get_from_kernel(sock._sock, 0, name)
551*4dc78e53SAndroid Build Coastguard Worker    if not link:
552*4dc78e53SAndroid Build Coastguard Worker        return None
553*4dc78e53SAndroid Build Coastguard Worker
554*4dc78e53SAndroid Build Coastguard Worker    return Link.from_capi(link)
555*4dc78e53SAndroid Build Coastguard Worker
556*4dc78e53SAndroid Build Coastguard Worker
557*4dc78e53SAndroid Build Coastguard Worker_link_cache = LinkCache()
558*4dc78e53SAndroid Build Coastguard Worker
559*4dc78e53SAndroid Build Coastguard Worker
560*4dc78e53SAndroid Build Coastguard Workerdef resolve(name):
561*4dc78e53SAndroid Build Coastguard Worker    _link_cache.refill()
562*4dc78e53SAndroid Build Coastguard Worker    return _link_cache[name]
563