net: conn_mgr: Write documentation

Write documentation for conn_mgr and its subsystems, especially
guidelines for writing connectivity implementations

Signed-off-by: Georges Oates_Larsen <georges.larsen@nordicsemi.no>
This commit is contained in:
Georges Oates_Larsen 2023-08-10 11:41:23 -07:00 committed by Carles Cufí
parent fe61d65b2e
commit 98a506f341
16 changed files with 1316 additions and 33 deletions

View file

@ -31,6 +31,8 @@ pointer or by a network interface index. The network interface can be
resolved from its index by calling ``net_if_get_by_index()`` and from interface
pointer by calling ``net_if_get_by_iface()``.
.. _net_if_interface_ip_management:
The IP address for network devices must be set for them to be connectable.
In a typical dynamic network environment, IP addresses are set automatically
by DHCPv4, for example. If needed though, the application can set a device's
@ -55,6 +57,8 @@ network technology supports promiscuous mode, then it is possible to receive
all the network packets that the network device driver is able to receive.
See :ref:`promiscuous_interface` API for more details.
.. _net_if_interface_state_management:
Network interface state management
**********************************

View file

@ -42,6 +42,8 @@ To avoid extra cost, all :c:func:`net_mgmt` calls are direct. Though this
may change in a future release, it will not affect the users of this
function.
.. _net_mgmt_listening:
Listening to network events
***************************

View file

@ -0,0 +1,2 @@
# Ignore drawio backup files
.$*

View file

@ -0,0 +1,205 @@
<mxfile host="Electron" modified="2023-08-28T23:43:21.842Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.8 Chrome/114.0.5735.289 Electron/25.5.0 Safari/537.36" etag="tYLSXPfTSRMTc84KCMcT" version="21.6.8" type="device">
<diagram id="W1R5wPltpbE_ZV7s-k6x" name="Page-1">
<mxGraphModel dx="1050" dy="1727" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Db8zi3n4dXzB52SZQf6J-138" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="516" y="-192" width="465" height="407" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-30" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="544" y="260" width="310" height="177" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-10" value="&lt;div&gt;network&lt;/div&gt;&lt;div&gt;readiness&lt;/div&gt;&lt;div&gt;events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="646" y="-68" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-11" value="&lt;div&gt;Application&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="285" y="-122" width="116" height="559" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-22" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Zephyr ifaces (bound)&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1">
<mxGeometry x="634" y="273" width="208" height="75" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-23" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="641" y="289" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-24" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="775" y="289" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-25" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="708" y="289" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-26" value="&lt;div&gt;Zephyr ifaces (unbound)&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1">
<mxGeometry x="634" y="361" width="208" height="70" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-27" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="641" y="389" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-28" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="775" y="389" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-29" value="iface" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="708" y="389" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-31" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="549" y="138" width="293" height="61" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-32" value="&lt;div&gt;binding&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="708" y="154" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fillColor=default;strokeColor=default;startArrow=classic;startFill=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-33" target="Db8zi3n4dXzB52SZQf6J-46" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="880" y="290" as="targetPoint" />
<Array as="points">
<mxPoint x="805" y="131" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-33" value="&lt;div&gt;binding&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="775" y="154" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-34" value="&lt;div&gt;binding&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="641" y="154" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;jumpStyle=sharp;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;startArrow=classic;startFill=1;fillColor=default;" parent="1" source="Db8zi3n4dXzB52SZQf6J-45" target="Db8zi3n4dXzB52SZQf6J-34" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="671" y="62" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-45" value="&lt;div&gt;Connectivity&lt;/div&gt;&lt;div&gt;Implementation&lt;/div&gt;&lt;div&gt;(LTE)&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="859" y="32" width="95" height="60" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;jumpStyle=sharp;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;startArrow=classic;startFill=1;fillColor=default;" parent="1" source="Db8zi3n4dXzB52SZQf6J-46" target="Db8zi3n4dXzB52SZQf6J-32" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="738" y="116" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-46" value="&lt;div&gt;Connectivity&lt;/div&gt;&lt;div&gt;Implementation&lt;/div&gt;&lt;div&gt;(Wi-Fi)&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="859" y="101" width="95" height="60" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-55" value="&lt;div&gt;Connectivity&lt;/div&gt;&lt;div&gt;Bindings&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="558" y="154" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-56" value="&lt;div&gt;Zephyr&lt;/div&gt;&lt;div&gt;ifaces&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="563" y="270" width="33" height="36" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-61" value="LTE L2" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1009" y="32" width="58" height="60" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=default;startArrow=classic;startFill=1;fillColor=default;" parent="1" source="Db8zi3n4dXzB52SZQf6J-23" target="Db8zi3n4dXzB52SZQf6J-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;strokeColor=default;startArrow=classic;startFill=1;fillColor=default;" parent="1" source="Db8zi3n4dXzB52SZQf6J-24" target="Db8zi3n4dXzB52SZQf6J-33" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=default;startArrow=classic;startFill=1;fillColor=default;anchorPointDirection=1;" parent="1" source="Db8zi3n4dXzB52SZQf6J-25" target="Db8zi3n4dXzB52SZQf6J-32" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-68" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;strokeColor=#6c8ebf;fillColor=#dae8fc;exitX=0.003;exitY=0.199;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;edgeStyle=orthogonalEdgeStyle;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-30" target="Db8zi3n4dXzB52SZQf6J-124" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="402" y="284" as="sourcePoint" />
<mxPoint x="117.5" y="192.5" as="targetPoint" />
<Array as="points">
<mxPoint x="483" y="295" />
<mxPoint x="483" y="-123" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-71" value="&lt;div&gt;network&lt;/div&gt;&lt;div&gt;commands&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="510" y="68" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-72" value="&lt;div&gt;iface state&lt;/div&gt;&lt;div&gt;change events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="420" y="303" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-74" value="Wi-Fi L2 " style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1009" y="101.5" width="58" height="60" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-76" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;strokeColor=#6c8ebf;fillColor=#dae8fc;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-45" target="Db8zi3n4dXzB52SZQf6J-61" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="970" y="338.5" as="sourcePoint" />
<mxPoint x="1070" y="238.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-77" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;strokeColor=#6c8ebf;fillColor=#dae8fc;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-46" target="Db8zi3n4dXzB52SZQf6J-74" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="1063" y="276.5" as="sourcePoint" />
<mxPoint x="1163" y="176.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-89" value="&lt;div&gt;iface commands and events,&lt;/div&gt;&lt;div&gt;binding state updates,&lt;/div&gt;&lt;div&gt;network commands&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="684" y="72.5" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-91" value="&lt;div&gt;iface commands&lt;/div&gt;&lt;div&gt;and events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="544" y="226" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-113" value="&lt;div&gt;iface commands&lt;/div&gt;&lt;div&gt;and events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="405" y="395" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-122" value="Connectivity Control" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="549" y="-8" width="295" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-129" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=sharp;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=default;elbow=vertical;" parent="1" source="Db8zi3n4dXzB52SZQf6J-124" target="Db8zi3n4dXzB52SZQf6J-122" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-124" value="Connectivity Monitoring" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="549" y="-148" width="295" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-128" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;comic=0;sketch=0;strokeColor=#6c8ebf;fillColor=#dae8fc;elbow=vertical;jumpStyle=sharp;jumpSize=23;edgeStyle=orthogonalEdgeStyle;entryX=0.285;entryY=0.021;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.281;exitY=1.003;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-122" target="Db8zi3n4dXzB52SZQf6J-31" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="589" y="41" as="sourcePoint" />
<mxPoint x="591" y="140" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-131" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;strokeColor=#6c8ebf;fillColor=#dae8fc;exitX=0.003;exitY=0.199;exitDx=0;exitDy=0;edgeStyle=orthogonalEdgeStyle;exitPerimeter=0;" parent="1" target="Db8zi3n4dXzB52SZQf6J-11" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="545.93" y="295.22299999999996" as="sourcePoint" />
<mxPoint x="416" y="-123" as="targetPoint" />
<Array as="points">
<mxPoint x="483" y="295" />
<mxPoint x="483" y="-101" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-132" value="" style="endArrow=classic;html=1;rounded=0;comic=0;sketch=0;strokeColor=default;fillColor=#CCE5FF;elbow=vertical;jumpStyle=sharp;jumpSize=23;edgeStyle=orthogonalEdgeStyle;entryX=0;entryY=0.5;entryDx=0;entryDy=0;startArrow=classic;startFill=1;exitX=1.002;exitY=0.906;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-11" target="Db8zi3n4dXzB52SZQf6J-23" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="421" y="380" as="sourcePoint" />
<mxPoint x="515" y="376" as="targetPoint" />
<Array as="points">
<mxPoint x="406" y="385" />
<mxPoint x="606" y="384" />
<mxPoint x="606" y="304" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-133" value="" style="endArrow=classic;html=1;rounded=0;comic=0;sketch=0;strokeColor=default;fillColor=#CCE5FF;elbow=vertical;jumpStyle=sharp;jumpSize=23;edgeStyle=orthogonalEdgeStyle;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.922;exitDx=0;exitDy=0;exitPerimeter=0;startArrow=classic;startFill=1;" parent="1" source="Db8zi3n4dXzB52SZQf6J-11" target="Db8zi3n4dXzB52SZQf6J-27" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="428.0440000000001" y="393.7649999999999" as="sourcePoint" />
<mxPoint x="651" y="314" as="targetPoint" />
<Array as="points">
<mxPoint x="607" y="393" />
<mxPoint x="607" y="404" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-134" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;comic=0;sketch=0;strokeColor=#6c8ebf;fillColor=#dae8fc;elbow=vertical;jumpStyle=sharp;jumpSize=23;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-11" target="Db8zi3n4dXzB52SZQf6J-122" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="432" y="61" as="sourcePoint" />
<mxPoint x="482" y="11" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-135" value="&lt;div&gt;network&lt;/div&gt;&lt;div&gt;commands&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="351" y="22" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-136" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.987;entryY=0.142;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=default;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;noJump=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-124" target="Db8zi3n4dXzB52SZQf6J-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-139" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;Connection Manager&lt;br&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;" parent="1" vertex="1">
<mxGeometry x="664" y="-194" width="171" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -0,0 +1,100 @@
<mxfile host="Electron" modified="2023-08-28T23:41:19.284Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.8 Chrome/114.0.5735.289 Electron/25.5.0 Safari/537.36" etag="LLGj6geb5OPwGWt5pcNY" version="21.6.8" type="device">
<diagram id="W1R5wPltpbE_ZV7s-k6x" name="Page-1">
<mxGraphModel dx="1050" dy="1027" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Db8zi3n4dXzB52SZQf6J-169" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;fontSize=16;fillColor=none;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="527" y="-207" width="195" height="261" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-10" value="&lt;div&gt;network&lt;/div&gt;&lt;div&gt;readiness&lt;/div&gt;&lt;div&gt;events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="574" y="-81" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-11" value="&lt;div&gt;Application&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="271" y="-122" width="116" height="348" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-61" value="L2" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="714" y="173" width="108" height="51" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-71" value="&lt;div&gt;connectivity&lt;/div&gt;&lt;div&gt;commands&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="584" y="22" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-89" value="&lt;div&gt;iface commands&lt;/div&gt;&lt;div&gt;and events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="596" y="128" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-113" value="&lt;div&gt;iface commands&lt;/div&gt;&lt;div&gt;and events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="397" y="208" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-155" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;fontSize=16;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;" parent="1" source="Db8zi3n4dXzB52SZQf6J-122" target="Db8zi3n4dXzB52SZQf6J-150" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-122" value="Connectivity Control" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="552" y="-35" width="147" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-129" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=sharp;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.484;entryY=-0.006;entryDx=0;entryDy=0;strokeColor=default;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=default;elbow=vertical;entryPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-124" target="Db8zi3n4dXzB52SZQf6J-122" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-124" value="Connectivity Monitoring" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="549" y="-148" width="147" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-135" value="&lt;div&gt;network&lt;/div&gt;&lt;div&gt;commands&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="341" y="-8" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-136" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeColor=default;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;noJump=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-124" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="386" y="-59" as="targetPoint" />
<Array as="points">
<mxPoint x="622" y="-59" />
<mxPoint x="401" y="-59" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-139" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;Connection Manager&lt;br&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;" parent="1" vertex="1">
<mxGeometry x="543" y="-198" width="171" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-141" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.004;exitY=0.631;exitDx=0;exitDy=0;entryX=1.017;entryY=0.937;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=default;fontSize=16;startArrow=classic;startFill=1;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-144" target="Db8zi3n4dXzB52SZQf6J-11" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="547" y="191.75" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-166" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=default;fontSize=16;startArrow=none;startFill=0;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;" parent="1" source="Db8zi3n4dXzB52SZQf6J-144" target="Db8zi3n4dXzB52SZQf6J-124" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="468" y="186" />
<mxPoint x="468" y="-135" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-144" value="&lt;div&gt;Zephyr ifaces&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="552" y="173" width="147" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-158" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;fontSize=16;startArrow=classic;startFill=1;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;" parent="1" source="Db8zi3n4dXzB52SZQf6J-150" target="Db8zi3n4dXzB52SZQf6J-144" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-161" style="edgeStyle=orthogonalEdgeStyle;rounded=0;comic=0;sketch=0;jumpStyle=none;jumpSize=23;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.999;exitY=0.676;exitDx=0;exitDy=0;strokeColor=default;fontSize=16;startArrow=classic;startFill=1;endArrow=classic;endFill=1;fillColor=#CCE5FF;elbow=vertical;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-150" target="Db8zi3n4dXzB52SZQf6J-61" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="700" y="103" />
<mxPoint x="768" y="102" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-150" value="Connectivity Implementations" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="552" y="69" width="147" height="50" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-153" value="" style="endArrow=classic;html=1;rounded=0;comic=0;sketch=0;strokeColor=default;fontSize=16;fillColor=#CCE5FF;elbow=vertical;jumpStyle=none;jumpSize=23;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0.991;exitY=0.322;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="Db8zi3n4dXzB52SZQf6J-11" target="Db8zi3n4dXzB52SZQf6J-122" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="413" y="18" as="sourcePoint" />
<mxPoint x="463" y="-32" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-162" value="&lt;div&gt;connectivity&lt;/div&gt;&lt;div&gt;commands&lt;/div&gt;&lt;div&gt;and events&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="725" y="128" width="164" height="30" as="geometry" />
</mxCell>
<mxCell id="Db8zi3n4dXzB52SZQf6J-167" value="&lt;div&gt;iface events&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="426" y="162" width="164" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,475 @@
.. _conn_mgr_impl:
Connectivity Implementations
############################
.. _conn_mgr_impl_overview:
Overview
========
Connectivity implementations are technology-specific modules that allow specific Zephyr ifaces to support :ref:`Connectivity Control <conn_mgr_control>`.
They are responsible for translating generic :ref:`connectivity control API <conn_mgr_control_api>` calls into hardware-specific operations.
They are also responsible for implementing standardized :ref:`persistence and timeout <conn_mgr_control_persistence_timeouts>` behaviors.
See the :ref:`implementation guidelines <conn_mgr_impl_guidelines>` for details on writing conformant connectivity implementations.
.. _conn_mgr_impl_architecture:
Architecture
============
The :ref:`implementation API <conn_mgr_impl_api>` allows connectivity implementations to be :ref:`defined <conn_mgr_impl_defining>` at build time using :c:macro:`CONN_MGR_CONN_DEFINE`.
This creates a static instance of the :c:struct:`conn_mgr_conn_impl` struct, which then stores a reference to the passed in :c:struct:`conn_mgr_conn_api` struct (which should be populated with implementation callbacks).
Once defined, you can reference implementations by name and bind them to any unbound iface using :c:macro:`CONN_MGR_BIND_CONN`.
Make sure not to accidentally bind two connectivity implementations to a single iface.
Once the iface is bound, :ref:`connectivity control API <conn_mgr_control_api>` functions can be called on the iface, and they will be translated to the corresponding implementation functions in :c:struct:`conn_mgr_conn_api`.
Binding an iface does not directly modify its :c:struct:`iface struct <net_if>`.
Instead, an instance of :c:struct:`conn_mgr_conn_binding` is created and appended an internal :ref:`iterable section <iterable_sections_api>`.
This binding structure will contain a reference to the bound iface, the connectivity implementation it is bound to, as well as a pointer to a per-iface :ref:`context pointer <conn_mgr_impl_ctx>`.
This iterable section can then be iterated over to find out what (if any) connectivity implementation has been bound to a given iface.
This search process is used by most of the functions in the :ref:`connectivity control API <conn_mgr_control_api>`.
As such, these functions should be called sparingly, due to their relatively high search cost.
A single connectivity implementation may be bound to multiple ifaces.
See :ref:`conn_mgr_impl_guidelines_no_instancing` for more details.
.. _conn_mgr_integration_diagram_detailed:
.. figure:: figures/integration_diagram_detailed.svg
:alt: A detailed view of how Connection Manager integrates with Zephyr and the application.
:figclass: align-center
A detailed view of how Connection Manager integrates with Zephyr and the application.
See :ref:`here <conn_mgr_integration_diagram_simple>` for a simplified version.
.. _conn_mgr_impl_ctx:
Context Pointer
===============
Since a single connectivity implementation may be shared by several Zephyr ifaces, each binding instantiates a context container (of :ref:`configurable type <conn_mgr_impl_declaring>`) unique to that binding.
Each binding is then instantiated with a reference to that container, which implementations can then use to access per-iface state information.
See also :ref:`conn_mgr_impl_guidelines_binding_access` and :ref:`conn_mgr_impl_guidelines_no_instancing`.
.. _conn_mgr_impl_defining:
Defining an implementation
==========================
A connectivity implementation may be defined as follows:
.. code-block:: c
/* Create the API implementation functions */
int my_connect_impl(struct conn_mgr_conn_binding *const binding) {
/* Cause your underlying technology to associate */
}
int my_disconnect_impl(struct conn_mgr_conn_binding *const binding) {
/* Cause your underlying technology to disassociate */
}
void my_init_impl(struct conn_mgr_conn_binding *const binding) {
/* Perform any required initialization for your underlying technology */
}
/* Declare the API struct */
static struct conn_mgr_conn_api my_impl_api = {
.connect = my_connect_impl,
.disconnect = my_disconnect_impl,
.init = my_init_impl,
/* ... so on */
};
/* Define the implementation (named MY_CONNECTIVITY_IMPL) */
CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api);
.. note::
This does not work unless you also :ref:`declare the context pointer type <conn_mgr_impl_declaring_ctx>`.
.. _conn_mgr_impl_declaring:
Declaring an implementation publicly
====================================
Once defined, you can make a connectivity implementation available to other compilation units by declaring it (in a header file) as follows:
.. code-block:: c
:caption: ``my_connectivity_header.h``
CONN_MGR_CONN_DECLARE_PUBLIC(MY_CONNECTIVITY_IMPL);
The header file that contains this declaration must be included in any compilation units that need to reference the implementation.
.. _conn_mgr_impl_declaring_ctx:
Declaring a context type
========================
For :c:macro:`CONN_MGR_CONN_DEFINE` to work, you must declare a corresponding context pointer type.
This is because all connectivity bindings contain a :ref:`conn_mgr_impl_ctx` of their associated context pointer type.
If you are using :c:macro:`CONN_MGR_CONN_DECLARE_PUBLIC`, declare this type alongside the declaration:
.. code-block:: c
:caption: ``my_connectivity_impl.h``
#define MY_CONNECTIVITY_IMPL_CTX_TYPE struct my_context_type *
CONN_MGR_CONN_DECLARE_PUBLIC(MY_CONNECTIVITY_IMPL);
Then, make sure to include the header file before calling :c:macro:`CONN_MGR_CONN_DEFINE`:
.. code-block:: c
:caption: ``my_connectivity_impl.c``
#include "my_connectivity_impl.h"
CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api);
Otherwise, it is sufficient to simply declare the context pointer type immediately before the call to :c:macro:`CONN_MGR_CONN_DEFINE`:
.. code-block:: c
#define MY_CONNECTIVITY_IMPL_CTX_TYPE struct my_context_type *
CONN_MGR_CONN_DEFINE(MY_CONNECTIVITY_IMPL, &my_impl_api);
.. note::
Naming is important.
Your context pointer type declaration must use the same name as your implementation declaration, but with ``_CTX_TYPE`` appended.
In the previous example, the context type is named ``MY_CONNECTIVITY_IMPL_CTX_TYPE``, because ``MY_CONNECTIVITY_IMPL`` was used as the connectivity implementation name.
If your connectivity implementation does not need a context pointer, simply declare the type as void:
.. code-block:: c
#define MY_CONNECTIVITY_IMPL_CTX_TYPE void *
.. _conn_mgr_impl_binding:
Binding an iface to an implementation
=====================================
A defined connectivity implementation may be bound to an iface by calling :c:macro:`CONN_MGR_BIND_CONN` anywhere after the iface's device definition:
.. code-block:: c
/* Define an iface */
NET_DEVICE_INIT(my_iface,
/* ... the specifics here don't matter ... */
);
/* Now bind MY_CONNECTIVITY_IMPL to that iface --
* the name used should match with the above
*/
CONN_MGR_BIND_CONN(my_iface, MY_CONNECTIVITY_IMPL);
.. _conn_mgr_impl_guidelines:
Connectivity implementation guidelines
======================================
Rather than implement all features centrally, Connection Manager relies on each connectivity implementation to implement many behaviors and features individually.
This approach allows Connection Manager to remain lean, and allows each connectivity implementation to choose the most appropriate approach to these behaviors for itself.
However, it relies on trust that all connectivity implementations will faithfully implement the features that have been delegated to them.
To maintain consistency between all connectivity implementations, observe the following guidelines when writing your own implementation:
.. _conn_mgr_impl_guidelines_timeout_persistence:
*Completely implement timeout and persistence*
----------------------------------------------
All connectivity implementations must offer complete support for :ref:`timeout and persistence <conn_mgr_control_persistence_timeouts>`, such that a user can disable or enable these features, regardless of the inherent behavior of the underlying technology.
In other words, no matter how the underlying technology behaves, your implementation must make it appear to the end user to behave exactly as specified in the :ref:`conn_mgr_control_persistence_timeouts` section.
See :ref:`conn_mgr_impl_timeout_persistence` for a detailed technical discussion on implementing timeouts and persistence.
.. _conn_mgr_impl_guidelines_conformity:
*Conform to API specifications*
-------------------------------
Each :c:struct:`implementation API function <conn_mgr_conn_api>` you implement should behave as-described in the corresponding connectivity control API function.
For example, your implementation of :c:member:`conn_mgr_conn_api.connect` should conform to the behavior described for :c:func:`conn_mgr_if_connect`.
.. _conn_mgr_impl_guidelines_preconfig:
*Allow connectivity pre-configuration*
--------------------------------------
Connectivity implementations should provide means for applications to pre-configure all necessary connection parameters (for example, network SSID, or PSK, if applicable), before the call to :c:func:`conn_mgr_if_connect`.
It should not be necessary to provide this information as part of, or following the :c:func:`conn_mgr_if_connect` call, although implementations :ref:`should await this information if it is not provided <conn_mgr_impl_guidelines_await_config>`.
.. _conn_mgr_impl_guidelines_await_config:
*Await valid connectivity configuration*
----------------------------------------
If network association fails because the application pre-configured invalid connection parameters, or did not configure connection parameters at all, this should be treated as a network failure.
In other words, the connectivity implementation should not give up on the connection attempt, even if valid connection parameters have not been configured.
Instead, the connectivity implementation should asynchronously wait for valid connection parameters to be configured, either indefinitely, or until the configured :ref:`connectivity timeout <conn_mgr_control_timeouts>` elapses.
.. _conn_mgr_impl_guidelines_iface_state_reporting:
*Implement iface state reporting*
---------------------------------
All connectivity implementations must keep bound iface state up to date.
To be specific:
* Set the iface to dormant, carrier-down, or both during :c:member:`binding init <conn_mgr_conn_api.init>`.
* See :ref:`net_if_interface_state_management` for details regarding iface carrier and dormant states.
* Update dormancy and carrier state so that the iface is non-dormant and carrier-up whenever (and only when) association is complete and connectivity is ready.
* Set the iface either to dormant or to carrier-down as soon as interruption of service is detected.
* It is acceptable to gate this behind a small timeout (separate from the connection timeout) for network technologies where service is commonly intermittent.
* If the technology also handles IP assignment, ensure those IP addresses are :ref:`assigned to the iface <net_if_interface_ip_management>`.
.. note::
iface state updates do not necessarily need to be performed directly by connectivity implementations.
For instance:
* IP assignment is not necessary if :ref:`DHCP <dhcpv4_interface>` is used for the iface.
* The connectivity implementation does not need to update iface dormancy if the underlying :ref:`L2 implementation <net_l2_interface>` already does so.
.. _conn_mgr_impl_guidelines_iface_state_writeonly:
*Do not use iface state as implementation state*
------------------------------------------------
Zephyr ifaces may be accessed from other threads without respecting the binding mutex.
As such, Zephyr iface state may change unpredictably during connectivity implementation callbacks.
Therefore, do not base implementation behaviors on iface state.
Keep iface state updated to reflect network availability, but do not read iface state for any purpose.
If you need to keep track of dormancy or IP assignment, use a separate state variable stored in the :ref:`context pointer <conn_mgr_impl_ctx>`.
.. _conn_mgr_impl_guidelines_non_interference:
*Remain non-interferent*
------------------------
Connectivity implementations should not prevent applications from interacting directly with associated technology-specific APIs.
In other words, it should be possible for an application to directly use your underlying technology without breaking your connectivity implementation.
If exceptions to this are absolutely necessary, they should be constrained to specific API calls and should be documented.
.. note::
While connectivity implementations must not break, it is acceptable for implementations to have potentially unexpected behavior if applications attempt to directly control the association state.
For instance, if an application directly instructs an underlying technology to dissassociate, it would be acceptable for the connectivity implementation to interpret this as an unexpected connection loss and immediately attempt to re-associate.
.. _conn_mgr_impl_guidelines_non_blocking:
*Remain non-blocking*
---------------------
All connectivity implementation callbacks should be non-blocking.
For instance, calls to :c:member:`conn_mgr_conn_api.connect` should initiate a connection process and return immediately.
One exception is :c:member:`conn_mgr_conn_api.init`, whose implementations are permitted to block.
However, bear in mind that blocking during this callback will delay system init, so still consider offloading time-consuming tasks to a background thread.
.. _conn_mgr_impl_guidelines_immediate_api_readiness:
*Make API immediately ready*
----------------------------
Connectivity implementations must be ready to receive API calls immediately after :c:member:`conn_mgr_conn_api.init`.
For instance, a call to :c:member:`conn_mgr_conn_api.connect` must eventually lead to an association attempt, even if called immediately after :c:member:`conn_mgr_conn_api.init`.
If the underlying technology cannot be made ready for connect commands immediately when :c:member:`conn_mgr_conn_api.init` is called, calls to :c:member:`conn_mgr_conn_api.connect` must be queued in a non-blocking fashion, and then executed later when ready.
.. _conn_mgr_impl_guidelines_context_pointer:
*Do not store state information outside the context pointer*
------------------------------------------------------------
Connection Manager provides a context pointer to each binding.
Connectivity implementations should store all state information in this context pointer.
The only exception is connectivity implementations that are meant to be bound to only a single iface.
Such implementations may use statically declared state instead.
See also :ref:`conn_mgr_impl_guidelines_no_instancing`.
.. _conn_mgr_impl_guidelines_iface_access:
*Access ifaces only through binding structs*
--------------------------------------------
Do not use statically declared ifaces or externally acquire references to ifaces.
For example, do not use :c:func:`net_if_get_default` under the assumption that the bound iface will be the default iface.
Instead, always use the :c:member:`iface pointer <conn_mgr_conn_binding.iface>` provided by the relevant :c:struct:`binding struct <conn_mgr_conn_binding>`.
See also :ref:`conn_mgr_impl_guidelines_binding_access`.
.. _conn_mgr_impl_guidelines_bindings_optional:
*Make implementations optional at compile-time*
-----------------------------------------------
Connectivity implementations should provide a Kconfig option to enable or disable the implementation without affecting bound iface availability.
In other words, it should be possible to configure builds that include Connectivity Manager, as well as the iface that would have been bound to the implementation, but not the implementation itself, nor its binding.
.. _conn_mgr_impl_guidelines_no_instancing:
*Do not instance implementations*
---------------------------------
Do not declare a separate connectivity implementation for every iface you are going to bind to.
Instead, bind one global connectivity implementation to all of your ifaces, and use the context pointer to store state relevant to individual ifaces.
See also :ref:`conn_mgr_impl_guidelines_binding_access` and :ref:`conn_mgr_impl_guidelines_iface_access`.
.. _conn_mgr_impl_guidelines_binding_access:
*Do not access bindings without locking them*
---------------------------------------------
Bindings may be accessed and modified at random by multiple threads, so modifying or reading from a binding without first :c:func:`locking it <conn_mgr_binding_lock>` may lead to unpredictable behavior.
This applies to all descendents of the binding, including anything in the :ref:`context container <conn_mgr_impl_ctx>`.
Make sure to :c:func:`unlock <conn_mgr_binding_unlock>` the binding when you are done accessing it.
.. note::
A possible exception to this rule is if the resource in question is inherently thread-safe.
However, be careful taking advantage of this exception.
It may still be possible to create a race condition, for instance when accessing multiple thread-safe resources simultaneously.
Therefore, it is recommended to simply always lock the binding, whether or not the resource being accessed is inherently thread-safe.
.. _conn_mgr_impl_guidelines_support_builtins:
*Do not disable built-in features*
----------------------------------
Do not attempt to prevent the use of built-in features (such as :ref:`conn_mgr_control_persistence_timeouts` or :ref:`conn_mgr_control_automations`).
All connectivity implementations must fully support these features.
Implementations must not attempt to force certain features to be always enabled or always disabled.
.. _conn_mgr_impl_guidelines_trigger_events:
*Trigger connectivity control events*
-------------------------------------
Connectivity control :ref:`network management <net_mgmt_interface>` events are not triggered automatically by Connection Manager.
Connectivity implementations must trigger these events themselves.
Trigger :c:macro:`NET_EVENT_CONN_CMD_IF_TIMEOUT` when a connection :ref:`timeout <conn_mgr_control_timeouts>` occurs.
See :ref:`conn_mgr_control_events_timeout` for details.
Trigger :c:macro:`NET_EVENT_CONN_IF_FATAL_ERROR` when a fatal (non-recoverable) connection error occurs.
See :ref:`conn_mgr_control_events_fatal_error` for details.
See :ref:`net_mgmt_interface` for details on firing network management events.
.. _conn_mgr_impl_timeout_persistence:
Implementing timeouts and persistence
=====================================
First, see :ref:`conn_mgr_control_persistence_timeouts` for a high-level description of the expected behavior of timeouts and persistence.
Connectivity implementations must fully conform to that description, regardless of the behavior of the underlying connectivity technology.
Sometimes this means writing extra logic in the connectivity implementation to fake certain behaviors.
The following sections discuss various common edge-cases and nuances and how to handle them.
.. _conn_mgr_impl_tp_inherent_persistence:
*Inherently persistent technologies*
------------------------------------
If the underlying technology automatically attempts to reconnect or retry connection after connection loss or failure, the connectivity implementation must manually cancel such attempts when they are in conflict with timeout or persistence settings.
For example:
* If the underlying technology automatically attempts to reconnect after losing connection, and persistence is disabled for the iface, the connectivity implementation should immediately cancel this reconnection attempt.
* If a connection attempt times out on an iface whose underlying technology does not have a built-in timeout, the connectivity implementation must simulate a timeout by cancelling the connection attempt manually.
.. _conn_mgr_impl_tp_inherent_nonpersistence:
*Technologiess that give up on connection attempts*
---------------------------------------------------
If the underlying technology has no mechanism to retry connection attempts, or would give up on them before the user-configured timeout, or would not reconnect after connection loss, the connectivity implementation must manually re-request connection to counteract these deviances.
* If your underlying technology is not persistent, you must manually trigger reconnect attempts when persistence is enabled.
* If your underlying technology does not support a timeout, you must manually cancel connection attempts if the timeout is enabled.
* If your underlying technology forces a timeout, you must manually trigger a new connection attempts if that timeout is shorter than the Connection Manager timeout.
.. _conn_mgr_impl_tp_assoc_retry:
*Technologies with association retry*
-------------------------------------
Many underlying technologies do not usually associate in a single attempt.
Instead, these underlying technologies may need to make multiple back-to-back association attempts in a row, usually with a small delay.
In these situations, the connectivity implementation should treat this series of back-to-back association sub-attempts as a single unified connection attempt.
For instance, after a sub-attempt failure, persistence being disabled should not prevent further sub-attempts, since they all count as one single overall connection attempt.
See also :ref:`conn_mgr_impl_tp_persistence_during_connect`.
At which point a series of failed sub-attempts should be considered a failure of the connection attempt as a whole is up to each implementation to decide.
If the connection attempt crosses this threshold, but the configured timeout has not yet elapsed, or there is no timeout, sub-attempts should continue.
.. _conn_mgr_impl_tp_persistence_during_connect:
*Persistence during connection attempts*
----------------------------------------
Persistence should not affect any aspect of implementation behavior during a connection attempt.
Persistence should only affect whether or not connection attempts are automatically triggered after a connection loss.
The configured timeout should fully determine whether connection retry should be performed.
.. _conn_mgr_impl_api:
Implementation API
==================
Include header file :file:`include/zephyr/net/conn_mgr_connectivity_impl.h` to access these.
Only for use by connectivity implementations.
.. doxygengroup:: conn_mgr_connectivity_impl

View file

@ -0,0 +1,10 @@
.. _conn_mgr_docs:
Connection Manager
##################
.. toctree::
:maxdepth: 1
main.rst
implementation.rst

View file

@ -0,0 +1,446 @@
.. _conn_mgr_overview:
Overview
########
Connection Manager is a collection of optional Zephyr features that aim to allow applications to monitor and control connectivity (access to IP-capable networks) with minimal concern for the specifics of underlying network technologies.
Using Connection Manager, applications can use a single abstract API to control network association and monitor Internet access, and avoid excessive use of technology-specific boilerplate.
This allows an application to potentially support several very different connectivity technologies (for example, Wi-Fi and LTE) with a single codebase.
Applications can also use Connection Manager to generically manage and use multiple connectivity technologies simultaneously.
Structure
=========
Connection Manager is split into the following two subsystems:
* :ref:`Connectivity monitoring <conn_mgr_monitoring>` (header file :file:`include/zephyr/net/conn_mgr_monitoring.h`) monitors all available :ref:`Zephyr network interfaces (ifaces) <net_if_interface>` and triggers :ref:`network management <net_mgmt_interface>` events indicating when IP connectivity is gained or lost.
* :ref:`Connectivity control <conn_mgr_control>` (header file :file:`include/zephyr/net/conn_mgr_connectivity.h`) provides an abstract API for controlling iface network association.
.. _conn_mgr_integration_diagram_simple:
.. figure:: figures/integration_diagram_simplified.svg
:alt: A simplified view of how Connection Manager integrates with Zephyr and the application.
:figclass: align-center
A simplified view of how Connection Manager integrates with Zephyr and the application.
See :ref:`here <conn_mgr_integration_diagram_detailed>` for a more detailed version.
.. _conn_mgr_monitoring:
Connectivity monitoring
#######################
Connectivity monitoring tracks all available ifaces (whether or not they support :ref:`Connectivity control <conn_mgr_control>`) as they transition through various :ref:`operational states <net_if_interface_state_management>` and acquire or lose assigned IP addresses.
Each available iface is considered ready if it meets the following criteria:
* The iface is admin-up
* This means the iface has been instructed to become operational-up (ready for use). This is done by a call to :c:func:`net_if_up`.
* The iface is oper-up
* This means the interface is completely ready for use; It is online, and if applicable, has associated with a network.
* See :ref:`net_if_interface_state_management` for details.
* The iface has at least one assigned IP address
* Both IPv4 and IPv6 addresses are acceptable.
This condition is met as soon as one or both of these is assigned.
* See :ref:`net_if_interface` for details on iface IP assignment.
* The iface has not been ignored
* Ignored ifaces are always treated as unready.
* See :ref:`conn_mgr_monitoring_ignoring_ifaces` for more details.
.. note::
Typically, iface state and IP assignment are updated either by the iface's :ref:`L2 implementation <net_l2_interface>` or bound :ref:`connectivity implementation <conn_mgr_impl>`.
See :ref:`conn_mgr_impl_guidelines_iface_state_reporting` for details.
A ready iface ceases to be ready the moment any of the above conditions is lost.
When at least one iface is ready, the :c:macro:`NET_EVENT_L4_CONNECTED` :ref:`network management <net_mgmt_interface>` event is triggered, and IP connectivity is said to be ready.
Afterwards, ifaces can become ready or unready without firing additional events, so long as there always remains at least one ready iface.
When there are no longer any ready ifaces left, the :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management <net_mgmt_interface>` event is triggered, and IP connectivity is said to be unready.
.. _conn_mgr_monitoring_usage:
Usage
=====
Connectivity monitoring is enabled if the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER` Kconfig option is enabled.
To receive connectivity updates, create and register a listener for the :c:macro:`NET_EVENT_L4_CONNECTED` and :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management <net_mgmt_interface>` events:
.. code-block:: c
/* Callback struct where the callback will be stored */
struct net_mgmt_event_callback l4_callback;
/* Callback handler */
static void l4_event_handler(struct net_mgmt_event_callback *cb,
uint32_t event, struct net_if *iface)
{
if (event == NET_EVENT_L4_CONNECTED) {
LOG_INF("Network connectivity gained!");
} else if (event == NET_EVENT_L4_DISCONNECTED) {
LOG_INF("Network connectivity lost!");
}
/* Otherwise, it's some other event type we didn't register for. */
}
/* Call this before Connection Manager monitoring initializes */
static void my_application_setup(void)
{
/* Configure the callback struct to respond to (at least) the L4_CONNECTED
* and L4_DISCONNECTED events.
*
*
* Note that the callback may also be triggered for events other than those specified here!
* (See the net_mgmt documentation)
*/
net_mgmt_init_event_callback(
&l4_callback, l4_event_handler,
NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED
);
/* Register the callback */
net_mgmt_add_event_callback(&l4_callback);
}
See :ref:`net_mgmt_listening` for more details on listening for net_mgmt events.
.. note::
To avoid missing initial connectivity events, you should register your listener(s) before Connection Manager monitoring initializes.
See :ref:`conn_mgr_monitoring_missing_notifications` for strategies to ensure this.
.. _conn_mgr_monitoring_missing_notifications:
Avoiding missed notifications
=============================
Connectivity monitoring may trigger events immediately upon initialization.
If your application registers its event listeners after connectivity monitoring initializes, it is possible to miss this first wave of events, and not be informed the first time network connectivity is gained.
If this is a concern, your application should :ref:`register its event listeners <conn_mgr_monitoring_usage>` before connectivity monitoring initializes.
Connectivity monitoring initializes using the :c:macro:`SYS_INIT` ``APPLICATION`` initialization priority specified by the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER_MONITOR_PRIORITY` Kconfig option.
You can register your callbacks before this initialization by using :c:macro:`SYS_INIT` with an earlier initialization priority than this value, for instance priority 0:
.. code-block:: C
static int my_application_setup(void)
{
/* Register callbacks here */
return 0;
}
SYS_INIT(my_application_setup, APPLICATION, 0);
If this is not feasible, you can instead request that connectivity monitoring resend the latest connectivity events at any time by calling :c:func:`conn_mgr_mon_resend_status`:
.. code-block:: C
static void my_late_application_setup(void)
{
/* Register callbacks here */
/* Once done, request that events be re-triggered */
conn_mgr_mon_resend_status();
}
.. _conn_mgr_monitoring_ignoring_ifaces:
Ignoring ifaces
===============
Applications can request that ifaces be ignored by Connection Manager by calling :c:func:`conn_mgr_ignore_iface` with the iface to be ignored.
Alternatively, an entire :ref:`L2 implementation <net_l2_interface>` can be ignored by calling :c:func:`conn_mgr_ignore_l2`.
This has the effect of individually ignoring all the ifaces using that :ref:`L2 implementation <net_l2_interface>`.
While ignored, the iface is treated by Connection Manager as though it were unready for network traffic, no matter its actual state.
This may be useful, for instance, if your application has configured one or more ifaces that cannot (or for whatever reason should not) be used to contact the wider Internet.
:ref:`Bulk convenience functions <conn_mgr_control_api_bulk>` optionally skip ignored ifaces.
See :c:func:`conn_mgr_ignore_iface` and :c:func:`conn_mgr_watch_iface` for more details.
.. _conn_mgr_monitoring_api:
Connectivity monitoring API
===========================
Include header file :file:`include/zephyr/net/conn_mgr_monitoring.h` to access these.
.. doxygengroup:: conn_mgr
.. _conn_mgr_control:
Connectivity control
####################
Many network interfaces require a network association procedure to be completed before being usable.
For such ifaces, connectivity control can provide a generic API to request network association (:c:func:`conn_mgr_if_connect`) and dissasociation (:c:func:`conn_mgr_if_disconnect`).
Network interfaces implement support for this API by :ref:`binding themselves to a connectivity implementation <conn_mgr_impl_binding>`.
Using this API, applications can associate with networks with minimal technology-specific boilerplate.
Connectivity control also provides the following additional features:
* Standardized :ref:`persistence and timeout <conn_mgr_control_persistence_timeouts>` behaviors during association.
* :ref:`Bulk functions <conn_mgr_control_api_bulk>` for controlling the admin state and network association of all available ifaces simultaneously.
* Optional :ref:`convenience automations <conn_mgr_control_automations>` for common connectivity actions.
.. _conn_mgr_control_operation:
Basic operation
===============
The following sections outline the basic operation of Connection Manager's connectivity control.
.. _conn_mgr_control_operation_binding:
Binding
-------
Before an iface can be commanded to associate or dissasociate using Connection Manager, it must first be bound to a :ref:`connectivity implementation <conn_mgr_impl>`.
Binding is performed by the provider of the iface, not by the application (see :ref:`conn_mgr_impl_binding`), and can be thought of as an extension of the iface declaration.
Once an iface is bound, all connectivity commands passed to it (such as :c:func:`conn_mgr_if_connect` or :c:func:`conn_mgr_if_disconnect`) will be routed to the corresponding implementation function in the connectivity implementation.
.. note::
To avoid inconsistent behavior, all connectivity implementations must adhere to the :ref:`implementation guidelines <conn_mgr_impl_guidelines>`.
.. _conn_mgr_control_operation_connecting:
Connecting
----------
Once a bound iface is admin-up (see :ref:`net_if_interface_state_management`), :c:func:`conn_mgr_if_connect` can be called to cause it to associate with a network.
If association succeeds, the connectivity implementation will mark the iface as operational-up (see :ref:`net_if_interface_state_management`).
If association fails unrecoverably, the :ref:`fatal error event <conn_mgr_control_events_fatal_error>` will be triggered.
You can configure an optional :ref:`timeout <conn_mgr_control_timeouts>` for this process.
.. note::
The :c:func:`conn_mgr_if_connect` function is intentionally minimalistic, and does not take any kind of configuration.
Each connectivity implementation should provide a way to pre-configure or automatically configure any required association settings or credentials.
See :ref:`conn_mgr_impl_guidelines_preconfig` for details.
.. _conn_mgr_control_operation_loss:
Connection loss
---------------
If connectivity is lost due to external factors, the connectivity implementation will mark the iface as operational-down.
Depending on whether :ref:`persistence <conn_mgr_control_persistence>` is set, the iface may then attempt to reconnect.
.. _conn_mgr_control_operation_disconnection:
Manual disconnection
--------------------
The application can also request that connectivity be intentionally abandoned by calling :c:func:`conn_mgr_if_disconnect`.
In this case, the connectivity implementation will disassociate the iface from its network and mark the iface as operational-down (see :ref:`net_if_interface_state_management`).
A new connection attempt will not be initiated, regardless of whether persistence is enabled.
.. _conn_mgr_control_persistence_timeouts:
Timeouts and Persistence
========================
Connection Manager requires that all connectivity implementations support the following standard key features:
* :ref:`Connection timeouts <conn_mgr_control_timeouts>`
* :ref:`Connection persistence <conn_mgr_control_persistence>`
These features describe how ifaces should behave during connect and disconnect events.
You can individually set them for each iface.
.. note::
It is left to connectivity implementations to successfully and accurately implement these two features as described below.
See :ref:`conn_mgr_impl_timeout_persistence` for more details from the connectivity implementation perspective.
.. _conn_mgr_control_timeouts:
Connection Timeouts
-------------------
When :c:func:`conn_mgr_if_connect` is called on an iface, a connection attempt begins.
The connection attempt continues indefinitely until it succeeds, unless a timeout has been specified for the iface (using :c:func:`conn_mgr_if_set_timeout`).
In that case, the connection attempt will be abandoned if the timeout elapses before it succeeds.
If this happens, the :ref:`timeout event<conn_mgr_control_events_timeout>` is raised.
.. _conn_mgr_control_persistence:
Connection Persistence
----------------------
Each iface also has a connection persistence setting that you can enable or disable by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_PERSISTENT` flag with :c:func:`conn_mgr_binding_set_flag`.
This setting specifies how the iface should handle unintentional connection loss.
If persistence is enabled, any unintentional connection loss will initiate a new connection attempt, with a new timeout if applicable.
Otherwise, the iface will not attempt to reconnect.
.. note::
Persistence not does affect connection attempt behavior.
Only the timeout setting affects this.
For instance, if a connection attempt on an iface times out, the iface will not attempt to reconnect, even if it is persistent.
Conversely, if there is not a specified timeout, the iface will try to connect forever until it succeeds, even if it is not persistent.
See :ref:`conn_mgr_impl_tp_persistence_during_connect` for the equivalent implementation guideline.
.. _conn_mgr_control_events:
Control events
==============
Connectivity control triggers :ref:`network management <net_mgmt_interface>` events to inform the application of important state changes.
See :ref:`conn_mgr_impl_guidelines_trigger_events` for the corresponding connectivity implementation guideline.
.. _conn_mgr_control_events_fatal_error:
Fatal Error
-----------
The :c:macro:`NET_EVENT_CONN_IF_FATAL_ERROR` event is raised when an iface encounters an error from which it cannot recover (meaning any subsequent attempts to associate are guaranteed to fail, and all such attempts should be abandoned).
Handlers of this event will be passed a pointer to the iface for which the fatal error occurred.
Individual connectivity implementations may also pass an application-specific data pointer.
.. _conn_mgr_control_events_timeout:
Timeout
-------
The :c:macro:`NET_EVENT_CONN_IF_TIMEOUT` event is raised when an :ref:`iface association <conn_mgr_control_operation_connecting>` attempt :ref:`times out <conn_mgr_control_timeouts>`.
Handlers of this event will be passed a pointer to the iface that timed out attempting to associate.
.. _conn_mgr_control_events_listening:
Listening for control events
----------------------------
You can listen for control events as follows:
.. code-block:: c
/* Declare a net_mgmt callback struct to store the callback */
struct net_mgmt_event_callback my_conn_evt_callback;
/* Declare a handler to receive control events */
static void my_conn_evt_handler(struct net_mgmt_event_callback *cb,
uint32_t event, struct net_if *iface)
{
if (event == NET_EVENT_CONN_IF_TIMEOUT) {
/* Timeout occurred, handle it */
} else if (event == NET_EVENT_CONN_IF_FATAL_ERROR) {
/* Fatal error occurred, handle it */
}
/* Otherwise, it's some other event type we didn't register for. */
}
int main()
{
/* Configure the callback struct to respond to (at least) the CONN_IF_TIMEOUT
* and CONN_IF_FATAL_ERROR events.
*
* Note that the callback may also be triggered for events other than those specified here!
* (See the net_mgmt documentation)
*/
net_mgmt_init_event_callback(
&conn_mgr_conn_callback, conn_mgr_conn_handler,
NET_EVENT_CONN_IF_TIMEOUT | NET_EVENT_CONN_IF_FATAL_ERROR
);
/* Register the callback */
net_mgmt_add_event_callback(&conn_mgr_conn_callback);
return 0;
}
See :ref:`net_mgmt_listening` for more details on listening for net_mgmt events.
.. _conn_mgr_control_automations:
Automated behaviors
===================
There are a few actions related to connectivity that are (by default at least) performed automatically for the user.
.. _conn_mgr_control_automations_auto_up:
.. topic:: Automatic admin-up
In Zephyr, ifaces are automatically taken admin-up (see :ref:`net_if_interface_state_management` for details on iface states) during initialization.
Applications can disable this behavior by setting the :c:enumerator:`~net_if_flag.NET_IF_NO_AUTO_START` interface flag with :c:func:`net_if_flag_set`.
.. _conn_mgr_control_automations_auto_connect:
.. topic:: Automatic connect
By default, Connection Manager will automatically connect any :ref:`bound <conn_mgr_impl_binding>` iface that becomes admin-up.
Applications can disable this by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_NO_AUTO_CONNECT` connectivity flag with :c:func:`conn_mgr_if_set_flag`.
.. _conn_mgr_control_automations_auto_down:
.. topic:: Automatic admin-down
By default, Connection Manager will automatically take any bound iface admin-down if it has given up on associating.
Applications can disable this for all ifaces by disabling the :kconfig:option:`CONFIG_NET_CONNECTION_MANAGER_AUTO_IF_DOWN` Kconfig option, or for individual ifaces by setting the :c:enumerator:`~conn_mgr_if_flag.CONN_MGR_IF_NO_AUTO_DOWN` connectivity flag with with :c:func:`conn_mgr_if_set_flag`.
.. _conn_mgr_control_api:
Connectivity control API
========================
Include header file :file:`include/zephyr/net/conn_mgr_connectivity.h` to access these.
.. doxygengroup:: conn_mgr_connectivity
.. _conn_mgr_control_api_bulk:
Bulk API
--------
Connectivity control provides several bulk functions allowing all ifaces to be controlled at once.
You can restrict these functions to operate only on non-:ref:`ignored <conn_mgr_monitoring_ignoring_ifaces>` ifaces if desired.
Include header file :file:`include/zephyr/net/conn_mgr_connectivity.h` to access these.
.. doxygengroup:: conn_mgr_connectivity_bulk

View file

@ -16,3 +16,4 @@ operation of the stacks and how they were implemented.
networking_with_host.rst
network_monitoring.rst
api/index.rst
conn_mgr/index.rst

View file

@ -39,18 +39,25 @@ extern "C" {
NET_MGMT_EVENT_BIT)
#define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE)
/** @endcond */
enum net_event_conn_cmd {
NET_EVENT_CONN_CMD_IF_TIMEOUT = 1,
NET_EVENT_CONN_CMD_IF_FATAL_ERROR,
};
/**
* @brief net_mgmt event raised when a connection attempt times out
*/
#define NET_EVENT_CONN_IF_TIMEOUT \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IF_TIMEOUT)
/**
* @brief net_mgmt event raised when a non-recoverable connectivity error occurs on an iface
*/
#define NET_EVENT_CONN_IF_FATAL_ERROR \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IF_FATAL_ERROR)
/** @endcond */
/**
* @brief Per-iface connectivity flags
@ -76,7 +83,7 @@ enum conn_mgr_if_flag {
* No auto-down
*
* When set, conn_mgr will not automatically take the iface admin-down when it stops
* trying to connect, even if NET_CONNECTION_MANAGER_AUTO_IF_DOWN is enabled.
* trying to connect, even if CONFIG_NET_CONNECTION_MANAGER_AUTO_IF_DOWN is enabled.
*/
CONN_MGR_IF_NO_AUTO_DOWN,
@ -86,7 +93,9 @@ enum conn_mgr_if_flag {
/** @endcond */
};
/** Value to use with @ref conn_mgr_conn_binding.timeout to indicate no timeout */
/** Value to use with @ref conn_mgr_if_set_timeout and @ref conn_mgr_conn_binding.timeout to
* indicate no timeout
*/
#define CONN_MGR_IF_NO_TIMEOUT 0
/**
@ -95,7 +104,7 @@ enum conn_mgr_if_flag {
* If the provided iface has been bound to a connectivity implementation, initiate
* network connect/association.
*
* Automatically takes the iface admin-up (by calling net_if_up) if it isn't already.
* Automatically takes the iface admin-up (by calling @ref net_if_up) if it isn't already.
*
* Non-Blocking.
*
@ -231,23 +240,27 @@ int conn_mgr_if_get_timeout(struct net_if *iface);
*
* @param iface - Pointer to the network interface to modify.
* @param timeout - The timeout value to set (in seconds).
* Pass CONN_MGR_IF_NO_TIMEOUT to disable the timeout.
* Pass @ref CONN_MGR_IF_NO_TIMEOUT to disable the timeout.
* @retval 0 on success.
* @retval -ENOTSUP if the provided iface is not bound to a connectivity implementation.
*/
int conn_mgr_if_set_timeout(struct net_if *iface, int timeout);
/**
* @brief Initialize all connectivity implementation bindings
*
*
* @}
*/
/**
* @brief Connection Manager Bulk API
* @defgroup conn_mgr_connectivity_bulk Connection Manager Connectivity Bulk API
* @ingroup networking
* @{
*/
void conn_mgr_conn_init(void);
/**
* @brief Convenience function that takes all available ifaces into the admin-up state.
*
* Essentially a wrapper for net_if_up.
* Essentially a wrapper for @ref net_if_up.
*
* @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr.
* Otherwise, affect all ifaces.
@ -260,7 +273,7 @@ int conn_mgr_all_if_up(bool skip_ignored);
/**
* @brief Convenience function that takes all available ifaces into the admin-down state.
*
* Essentially a wrapper for net_if_down.
* Essentially a wrapper for @ref net_if_down.
*
* @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr.
* Otherwise, affect all ifaces.
@ -273,7 +286,7 @@ int conn_mgr_all_if_down(bool skip_ignored);
* @brief Convenience function that takes all available ifaces into the admin-up state, and
* connects those that support connectivity.
*
* Essentially a wrapper for net_if_up and conn_mgr_if_connect.
* Essentially a wrapper for @ref net_if_up and @ref conn_mgr_if_connect.
*
* @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr.
* Otherwise, affect all ifaces.
@ -286,7 +299,7 @@ int conn_mgr_all_if_connect(bool skip_ignored);
* @brief Convenience function that disconnects all available ifaces that support connectivity
* without putting them into admin-down state (unless auto-down is enabled for the iface).
*
* Essentially a wrapper for net_if_down.
* Essentially a wrapper for @ref net_if_down.
*
* @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr.
* Otherwise, affect all ifaces.

View file

@ -41,12 +41,12 @@ struct conn_mgr_conn_binding;
struct conn_mgr_conn_api {
/**
* @brief When called, the connectivity implementation should start attempting to
* establish connectivity for (associate with a network) the bound iface pointed
* establish connectivity (association with a network) for the bound iface pointed
* to by if_conn->iface.
*
* Must be non-blocking.
*
* Called by conn_mgr_if_connect.
* Called by @ref conn_mgr_if_connect.
*/
int (*connect)(struct conn_mgr_conn_binding *const binding);
@ -57,7 +57,7 @@ struct conn_mgr_conn_api {
*
* Must be non-blocking.
*
* Called by conn_mgr_if_disconnect.
* Called by @ref conn_mgr_if_disconnect.
*/
int (*disconnect)(struct conn_mgr_conn_binding *const binding);
@ -189,7 +189,7 @@ struct conn_mgr_conn_binding {
* The connectivity implementation should give up on establishing connectivity after this
* timeout, even if persistence is enabled.
*
* Set to CONN_MGR_IF_NO_TIMEOUT to indicate that no timeout should be used.
* Set to @ref CONN_MGR_IF_NO_TIMEOUT to indicate that no timeout should be used.
*/
int timeout;
@ -273,7 +273,7 @@ static inline void conn_mgr_binding_lock(struct conn_mgr_conn_binding *binding)
/**
* @brief Unlocks the passed-in binding.
*
* Call this after any call to conn_mgr_binding_lock once done accessing binding data.
* Call this after any call to @ref conn_mgr_binding_lock once done accessing binding data.
*
* Reentrant.
*
@ -289,13 +289,13 @@ static inline void conn_mgr_binding_unlock(struct conn_mgr_conn_binding *binding
/**
* @brief Set the value of the specified connectivity flag for the provided binding
*
* Can be used from any thread or callback without calling conn_mgr_binding_lock.
* Can be used from any thread or callback without calling @ref conn_mgr_binding_lock.
*
* For use only by connectivity implementations
*
* @param binding - The binding to check
* @param flag - The flag to check
* @param value - New value for the specified flag
* @param binding The binding to check
* @param flag The flag to check
* @param value New value for the specified flag
*/
static inline void conn_mgr_binding_set_flag(struct conn_mgr_conn_binding *binding,
enum conn_mgr_if_flag flag, bool value)
@ -313,13 +313,13 @@ static inline void conn_mgr_binding_set_flag(struct conn_mgr_conn_binding *bindi
/**
* @brief Check the value of the specified connectivity flag for the provided binding
*
* Can be used from any thread or callback without calling conn_mgr_binding_lock.
* Can be used from any thread or callback without calling @ref conn_mgr_binding_lock.
*
* For use only by connectivity implementations
*
* @param binding - The binding to check
* @param flag - The flag to check
* @return bool - The value of the specified flag
* @param binding The binding to check
* @param flag The flag to check
* @return bool The value of the specified flag
*/
static inline bool conn_mgr_binding_get_flag(struct conn_mgr_conn_binding *binding,
enum conn_mgr_if_flag flag)

View file

@ -11,7 +11,14 @@
extern "C" {
#endif
#if defined(CONFIG_NET_CONNECTION_MANAGER)
#if defined(CONFIG_NET_CONNECTION_MANAGER) || defined(__DOXYGEN__)
/**
* @brief Connection Manager API
* @defgroup conn_mgr Connection Manager API
* @ingroup networking
* @{
*/
struct net_if;
struct net_l2;
@ -31,7 +38,7 @@ void conn_mgr_mon_resend_status(void);
* and if the iface was connected before being ignored, events will be fired as though it
* disconnected at that moment.
*
* @param iface - iface to be ignored.
* @param iface iface to be ignored.
*/
void conn_mgr_ignore_iface(struct net_if *iface);
@ -44,14 +51,16 @@ void conn_mgr_ignore_iface(struct net_if *iface);
* and if the iface was connected before being watched, events will be fired as though
* it connected in that moment.
*
* @param iface - iface to no longer ignore.
* All ifaces default to watched at boot.
*
* @param iface iface to no longer ignore.
*/
void conn_mgr_watch_iface(struct net_if *iface);
/**
* @brief Check whether the provided iface is currently ignored.
*
* @param iface - The iface to check.
* @param iface The iface to check.
* @retval true if the iface is being ignored by conn_mgr.
* @retval false if the iface is being watched by conn_mgr.
*/
@ -62,7 +71,7 @@ bool conn_mgr_is_iface_ignored(struct net_if *iface);
*
* This is a wrapper for conn_mgr_ignore_iface that ignores all ifaces that use the L2.
*
* @param l2 - L2 to be ignored.
* @param l2 L2 to be ignored.
*/
void conn_mgr_ignore_l2(const struct net_l2 *l2);
@ -71,10 +80,14 @@ void conn_mgr_ignore_l2(const struct net_l2 *l2);
*
* This is a wrapper for conn_mgr_watch_iface that watches all ifaces that use the L2.
*
* @param l2 - L2 to watch.
* @param l2 L2 to watch.
*/
void conn_mgr_watch_l2(const struct net_l2 *l2);
/**
* @}
*/
#else
#define conn_mgr_mon_resend_status(...)

View file

@ -20,4 +20,7 @@ if(CONFIG_NETWORKING)
endif()
add_subdirectory(lib)
add_subdirectory_ifdef(CONFIG_NET_CONNECTION_MANAGER conn_mgr)
if(CONFIG_NET_CONNECTION_MANAGER)
add_subdirectory(conn_mgr)
endif()

View file

@ -56,4 +56,7 @@ extern struct k_mutex conn_mgr_mon_lock;
void conn_mgr_init_events_handler(void);
/* Cause conn_mgr_connectivity to Initialize all connectivity implementation bindings */
void conn_mgr_conn_init(void);
#endif /* __CONN_MGR_PRV_H__ */