1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
.. sockets:
Module architecture
^^^^^^^^^^^^^^^^^^^
Sockets
=======
The idea behind the pyroute2 framework is pretty simple. The
library provides socket objects, that have:
* shortcuts to establish netlink connections
* extra methods to run netlink queries
* some magic to handle packet bursts
* another magic to transparently mangle netlink messages
In other sense any netlink socket is just an ordinary socket
with `fileno()`, `recv()`, `sendto()` etc. Of course, one
can use it in `poll()`.
There is an inheritance diagram of Linux netlink sockets, provided
by the library:
.. inheritance-diagram:: pyroute2.iproute.linux.IPRoute
pyroute2.iproute.linux.IPBatch
pyroute2.iproute.linux.RawIPRoute
pyroute2.iproute.RemoteIPRoute
pyroute2.iwutil.IW
pyroute2.ipset.IPSet
pyroute2.netlink.uevent.UeventSocket
pyroute2.netlink.taskstats.TaskStats
pyroute2.netlink.generic.wireguard.WireGuard
pyroute2.netlink.generic.ethtool.NlEthtool
pyroute2.netlink.ipq.IPQSocket
pyroute2.netlink.nfnetlink.nfctsocket.NFCTSocket
pyroute2.netlink.nfnetlink.nftsocket.NFTSocket
pyroute2.netlink.event.EventSocket
pyroute2.netlink.event.acpi_event.AcpiEventSocket
pyroute2.netlink.event.dquot.DQuotSocket
pyroute2.netlink.event.thermal_event.ThermalEventSocket
pyroute2.netlink.devlink.DevlinkSocket
pyroute2.netlink.diag.DiagSocket
pyroute2.remote.RemoteSocket
pyroute2.remote.shell.ShellIPR
pyroute2.netns.nslink.NetNS
:parts: 1
under the hood
--------------
Let's assume we use an `IPRoute` object to get the
interface list of the system::
from pyroute2 import IPRoute
ipr = IPRoute()
ipr.get_links()
ipr.close()
The `get_links()` method is provided by the `IPRouteMixin`
class. It chooses the message to send (`ifinfmsg`), prepares
required fields and passes it to the next layer::
result.extend(self.nlm_request(msg, RTM_GETLINK, msg_flags))
The `nlm_request()` is a method of the `NetlinkMixin` class.
It wraps the pair request/response in one method. The request
is done via `put()`, response comes with `get()`. These
methods hide under the hood the asynchronous nature of the
netlink protocol, where the response can come whenever --
the time and packet order are not guaranteed. But one can
use the `sequence_number` field of a netlink message to
match responses, and the pair `put()/get()` does it.
cache thread
------------
Sometimes it is preferrable to get incoming messages asap
and parse them only when there is time for that. For that
case the `NetlinkMixin` provides a possibility to start a
dedicated cache thread, that will collect and queue incoming
messages as they arrive. The thread doesn't affect the
socket behaviour: it will behave exactly in the same way,
the only difference is that `recv()` will return already
cached in the userspace message. To start the thread,
one should call `bind()` with `async_cache=True`::
ipr = IPRoute()
ipr.bind(async_cache=True)
... # do some stuff
ipr.close()
message mangling
----------------
An interesting feature of the `IPRSocketMixin` is a netlink
proxy code, that allows to register callbacks for different
message types. The callback API is simple. The callback
must accept the message as a binary data, and must return
a dictionary with two keys, `verdict` and `data`. The
verdict can be:
* for `sendto()`: `forward`, `return` or `error`
* for `recv()`: `forward` or `error`
E.g.::
msg = ifinfmsg(data)
msg.decode()
... # mangle msg
msg.reset()
msg.encode()
return {'verdict': 'forward',
'data': msg.buf.getvalue()}
The `error` verdict raises an exception from `data`. The
`forward` verdict causes the `data` to be passed. The
`return` verdict is valid only in `sendto()` callbacks and
means that the `data` should not be passed to the kernel,
but instead it must be returned to the user.
This magic allows the library to transparently support
ovs, teamd, tuntap calls via netlink. The corresponding
callbacks transparently route the call to an external
utility or to `ioctl()` API.
How to register callbacks, see `IPRSocketMixin` init.
The `_sproxy` serves `sendto()` mangling, the `_rproxy`
serves the `recv()` mangling. Later this API can become
public.
Netlink messages
================
To handle the data going through the sockets, the library
uses different message classes. To create a custom message
type, one should inherit:
* `nlmsg` to create a netlink message class
* `genlmsg` to create generic netlink message class
* `nla` to create a NLA class
The messages hierarchy:
.. inheritance-diagram:: pyroute2.netlink.rtnl.ndmsg.ndmsg
pyroute2.netlink.rtnl.ndtmsg.ndtmsg
pyroute2.netlink.rtnl.tcmsg.tcmsg
pyroute2.netlink.rtnl.rtmsg.nlflags
pyroute2.netlink.rtnl.rtmsg.rtmsg_base
pyroute2.netlink.rtnl.rtmsg.rtmsg
pyroute2.netlink.rtnl.rtmsg.nh
pyroute2.netlink.rtnl.fibmsg.fibmsg
pyroute2.netlink.rtnl.ifaddrmsg.ifaddrmsg
pyroute2.netlink.rtnl.ifstatsmsg.ifstatsmsg
pyroute2.netlink.rtnl.ifinfmsg.ifinfmsg
pyroute2.netlink.rtnl.ifinfmsg.ifinfveth
pyroute2.netlink.rtnl.iw_event.iw_event
pyroute2.netlink.rtnl.nsidmsg.nsidmsg
pyroute2.netlink.rtnl.nsinfmsg.nsinfmsg
pyroute2.netlink.rtnl.rtgenmsg.rtgenmsg
pyroute2.netlink.devlink.devlinkcmd
pyroute2.netlink.diag.inet_addr_codec
pyroute2.netlink.diag.inet_diag_req
pyroute2.netlink.diag.inet_diag_msg
pyroute2.netlink.diag.unix_diag_req
pyroute2.netlink.diag.unix_diag_msg
pyroute2.netlink.event.acpi_event.acpimsg
pyroute2.netlink.event.dquot.dquotmsg
pyroute2.netlink.event.thermal_event.thermal_msg
pyroute2.netlink.taskstats.taskstatsmsg
pyroute2.netlink.taskstats.tcmd
pyroute2.netlink.generic.ethtool.ethtool_strset_msg
pyroute2.netlink.generic.ethtool.ethtool_linkinfo_msg
pyroute2.netlink.generic.ethtool.ethtool_linkmode_msg
pyroute2.netlink.generic.ethtool.ethtool_linkstate_msg
pyroute2.netlink.generic.ethtool.ethtool_wol_msg
pyroute2.netlink.generic.wireguard.wgmsg
pyroute2.netlink.ctrlmsg
pyroute2.netlink.genlmsg
pyroute2.netlink.nl80211.nl80211cmd
pyroute2.netlink.nfnetlink.ipset.ipset_msg
pyroute2.netlink.nfnetlink.nfgen_msg
pyroute2.netlink.nfnetlink.nftsocket.nft_gen_msg
pyroute2.netlink.nfnetlink.nftsocket.nft_chain_msg
pyroute2.netlink.nfnetlink.nftsocket.nft_rule_msg
pyroute2.netlink.nfnetlink.nftsocket.nft_set_msg
pyroute2.netlink.nfnetlink.nftsocket.nft_table_msg
pyroute2.netlink.nfnetlink.nfctsocket.nfct_stats
pyroute2.netlink.nfnetlink.nfctsocket.nfct_stats_cpu
pyroute2.netlink.nfnetlink.nfctsocket.nfct_msg
pyroute2.netlink.ipq.ipq_mode_msg
pyroute2.netlink.ipq.ipq_packet_msg
pyroute2.netlink.ipq.ipq_verdict_msg
pyroute2.netlink.uevent.ueventmsg
:parts: 1
PF_ROUTE messages
=================
PF_ROUTE socket is used to receive notifications from the BSD
kernel. The PF_ROUTE messages:
.. inheritance-diagram:: pyroute2.bsd.pf_route.freebsd.bsdmsg
pyroute2.bsd.pf_route.freebsd.if_msg
pyroute2.bsd.pf_route.freebsd.rt_msg_base
pyroute2.bsd.pf_route.freebsd.ifa_msg_base
pyroute2.bsd.pf_route.freebsd.ifma_msg_base
pyroute2.bsd.pf_route.freebsd.if_announcemsg
pyroute2.bsd.pf_route.rt_slot
pyroute2.bsd.pf_route.rt_msg
pyroute2.bsd.pf_route.ifa_msg
pyroute2.bsd.pf_route.ifma_msg
:parts: 1
IPDB
====
The `IPDB` module implements high-level logic to manage
some of the system network settings. It is completely
agnostic to the netlink object's nature, the only requirement
is that the netlink transport must provide RTNL API.
So, using proper mixin classes one can create a custom
RTNL-compatible transport. E.g., this way `IPDB` can work
over `NetNS` objects, providing the network management
within some network namespace — while itself it runs in the
main namespace.
The `IPDB` architecture is not too complicated, but it
implements some useful transaction magic, see `commit()`
methods of the `Transactional` objects.
.. inheritance-diagram:: pyroute2.ipdb.main.IPDB
pyroute2.ipdb.interfaces.Interface
pyroute2.ipdb.linkedset.LinkedSet
pyroute2.ipdb.linkedset.IPaddrSet
pyroute2.ipdb.routes.NextHopSet
pyroute2.ipdb.routes.Via
pyroute2.ipdb.routes.Encap
pyroute2.ipdb.routes.Metrics
pyroute2.ipdb.routes.BaseRoute
pyroute2.ipdb.routes.Route
pyroute2.ipdb.routes.MPLSRoute
pyroute2.ipdb.routes.RoutingTable
pyroute2.ipdb.routes.MPLSTable
pyroute2.ipdb.routes.RoutingTableSet
pyroute2.ipdb.rules.Rule
pyroute2.ipdb.rules.RulesDict
:parts: 1
Internet protocols
==================
Beside of the netlink protocols, the library implements a
limited set of supplementary internet protocol to play with.
.. inheritance-diagram:: pyroute2.protocols.udpmsg
pyroute2.protocols.ip4msg
pyroute2.protocols.udp4_pseudo_header
pyroute2.protocols.ethmsg
pyroute2.dhcp.dhcp4msg.dhcp4msg
:parts: 1
|