Nathan Skrzypczak | 9ad39c0 | 2021-08-19 11:38:06 +0200 | [diff] [blame] | 1 | Feature Arcs |
| 2 | ============ |
| 3 | |
| 4 | A significant number of vpp features are configurable on a per-interface |
| 5 | or per-system basis. Rather than ask feature coders to manually |
| 6 | construct the required graph arcs, we built a general mechanism to |
| 7 | manage these mechanics. |
| 8 | |
| 9 | Specifically, feature arcs comprise ordered sets of graph nodes. Each |
| 10 | feature node in an arc is independently controlled. Feature arc nodes |
| 11 | are generally unaware of each other. Handing a packet to “the next |
| 12 | feature node” is quite inexpensive. |
| 13 | |
| 14 | The feature arc implementation solves the problem of creating graph arcs |
| 15 | used for steering. |
| 16 | |
| 17 | At the beginning of a feature arc, a bit of setup work is needed, but |
| 18 | only if at least one feature is enabled on the arc. |
| 19 | |
| 20 | On a per-arc basis, individual feature definitions create a set of |
| 21 | ordering dependencies. Feature infrastructure performs a topological |
| 22 | sort of the ordering dependencies, to determine the actual feature |
| 23 | order. Missing dependencies **will** lead to runtime disorder. See |
| 24 | https://gerrit.fd.io/r/#/c/12753 for an example. |
| 25 | |
| 26 | If no partial order exists, vpp will refuse to run. Circular dependency |
| 27 | loops of the form “a then b, b then c, c then a” are impossible to |
| 28 | satisfy. |
| 29 | |
| 30 | Adding a feature to an existing feature arc |
| 31 | ------------------------------------------- |
| 32 | |
| 33 | To nobody’s great surprise, we set up feature arcs using the typical |
| 34 | “macro -> constructor function -> list of declarations” pattern: |
| 35 | |
| 36 | .. code:: c |
| 37 | |
| 38 | VNET_FEATURE_INIT (mactime, static) = |
| 39 | { |
| 40 | .arc_name = "device-input", |
| 41 | .node_name = "mactime", |
| 42 | .runs_before = VNET_FEATURES ("ethernet-input"), |
| 43 | }; |
| 44 | |
| 45 | This creates a “mactime” feature on the “device-input” arc. |
| 46 | |
| 47 | Once per frame, dig up the vnet_feature_config_main_t corresponding to |
| 48 | the “device-input” feature arc: |
| 49 | |
| 50 | .. code:: c |
| 51 | |
| 52 | vnet_main_t *vnm = vnet_get_main (); |
| 53 | vnet_interface_main_t *im = &vnm->interface_main; |
| 54 | u8 arc = im->output_feature_arc_index; |
| 55 | vnet_feature_config_main_t *fcm; |
| 56 | |
| 57 | fcm = vnet_feature_get_config_main (arc); |
| 58 | |
| 59 | Note that in this case, we’ve stored the required arc index - assigned |
| 60 | by the feature infrastructure - in the vnet_interface_main_t. Where to |
| 61 | put the arc index is a programmer’s decision when creating a feature |
| 62 | arc. |
| 63 | |
| 64 | Per packet, set next0 to steer packets to the next node they should |
| 65 | visit: |
| 66 | |
| 67 | .. code:: c |
| 68 | |
| 69 | vnet_get_config_data (&fcm->config_main, |
| 70 | &b0->current_config_index /* value-result */, |
| 71 | &next0, 0 /* # bytes of config data */); |
| 72 | |
| 73 | Configuration data is per-feature arc, and is often unused. Note that |
| 74 | it’s normal to reset next0 to divert packets elsewhere; often, to drop |
| 75 | them for cause: |
| 76 | |
| 77 | .. code:: c |
| 78 | |
| 79 | next0 = MACTIME_NEXT_DROP; |
| 80 | b0->error = node->errors[DROP_CAUSE]; |
| 81 | |
| 82 | Creating a feature arc |
| 83 | ---------------------- |
| 84 | |
| 85 | Once again, we create feature arcs using constructor macros: |
| 86 | |
| 87 | .. code:: c |
| 88 | |
| 89 | VNET_FEATURE_ARC_INIT (ip4_unicast, static) = |
| 90 | { |
| 91 | .arc_name = "ip4-unicast", |
| 92 | .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"), |
| 93 | .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index, |
| 94 | }; |
| 95 | |
| 96 | In this case, we configure two arc start nodes to handle the |
| 97 | “hardware-verified ip checksum or not” cases. During initialization, the |
| 98 | feature infrastructure stores the arc index as shown. |
| 99 | |
| 100 | In the head-of-arc node, do the following to send packets along the |
| 101 | feature arc: |
| 102 | |
| 103 | .. code:: c |
| 104 | |
| 105 | ip_lookup_main_t *lm = &im->lookup_main; |
| 106 | arc = lm->ucast_feature_arc_index; |
| 107 | |
| 108 | Once per packet, initialize packet metadata to walk the feature arc: |
| 109 | |
| 110 | .. code:: c |
| 111 | |
| 112 | vnet_feature_arc_start (arc, sw_if_index0, &next, b0); |
| 113 | |
| 114 | Enabling / Disabling features |
| 115 | ----------------------------- |
| 116 | |
| 117 | Simply call vnet_feature_enable_disable to enable or disable a specific |
| 118 | feature: |
| 119 | |
| 120 | .. code:: c |
| 121 | |
| 122 | vnet_feature_enable_disable ("device-input", /* arc name */ |
| 123 | "mactime", /* feature name */ |
| 124 | sw_if_index, /* Interface sw_if_index */ |
| 125 | enable_disable, /* 1 => enable */ |
| 126 | 0 /* (void *) feature_configuration */, |
| 127 | 0 /* feature_configuration_nbytes */); |
| 128 | |
| 129 | The feature_configuration opaque is seldom used. |
| 130 | |
| 131 | If you wish to make a feature a *de facto* system-level concept, pass |
| 132 | sw_if_index=0 at all times. Sw_if_index 0 is always valid, and |
| 133 | corresponds to the “local” interface. |
| 134 | |
| 135 | Related “show” commands |
| 136 | ----------------------- |
| 137 | |
| 138 | To display the entire set of features, use “show features [verbose]”. |
| 139 | The verbose form displays arc indices, and feature indicies within the |
| 140 | arcs |
| 141 | |
| 142 | :: |
| 143 | |
| 144 | $ vppctl show features verbose |
| 145 | Available feature paths |
| 146 | <snip> |
| 147 | [14] ip4-unicast: |
| 148 | [ 0]: nat64-out2in-handoff |
| 149 | [ 1]: nat64-out2in |
| 150 | [ 2]: nat44-ed-hairpin-dst |
| 151 | [ 3]: nat44-hairpin-dst |
| 152 | [ 4]: ip4-dhcp-client-detect |
| 153 | [ 5]: nat44-out2in-fast |
| 154 | [ 6]: nat44-in2out-fast |
| 155 | [ 7]: nat44-handoff-classify |
| 156 | [ 8]: nat44-out2in-worker-handoff |
| 157 | [ 9]: nat44-in2out-worker-handoff |
| 158 | [10]: nat44-ed-classify |
| 159 | [11]: nat44-ed-out2in |
| 160 | [12]: nat44-ed-in2out |
| 161 | [13]: nat44-det-classify |
| 162 | [14]: nat44-det-out2in |
| 163 | [15]: nat44-det-in2out |
| 164 | [16]: nat44-classify |
| 165 | [17]: nat44-out2in |
| 166 | [18]: nat44-in2out |
| 167 | [19]: ip4-qos-record |
| 168 | [20]: ip4-vxlan-gpe-bypass |
| 169 | [21]: ip4-reassembly-feature |
| 170 | [22]: ip4-not-enabled |
| 171 | [23]: ip4-source-and-port-range-check-rx |
| 172 | [24]: ip4-flow-classify |
| 173 | [25]: ip4-inacl |
| 174 | [26]: ip4-source-check-via-rx |
| 175 | [27]: ip4-source-check-via-any |
| 176 | [28]: ip4-policer-classify |
| 177 | [29]: ipsec-input-ip4 |
| 178 | [30]: vpath-input-ip4 |
| 179 | [31]: ip4-vxlan-bypass |
| 180 | [32]: ip4-lookup |
| 181 | <snip> |
| 182 | |
| 183 | Here, we learn that the ip4-unicast feature arc has index 14, and that |
| 184 | e.g. ip4-inacl is the 25th feature in the generated partial order. |
| 185 | |
| 186 | To display the features currently active on a specific interface, use |
| 187 | “show interface features”: |
| 188 | |
| 189 | :: |
| 190 | |
| 191 | $ vppctl show interface GigabitEthernet3/0/0 features |
| 192 | Feature paths configured on GigabitEthernet3/0/0... |
| 193 | <snip> |
| 194 | ip4-unicast: |
| 195 | nat44-out2in |
| 196 | <snip> |
| 197 | |
| 198 | Table of Feature Arcs |
| 199 | --------------------- |
| 200 | |
| 201 | Simply search for name-strings to track down the arc definition, |
| 202 | location of the arc index, etc. |
| 203 | |
| 204 | :: |
| 205 | |
| 206 | | Arc Name | |
| 207 | |------------------| |
| 208 | | device-input | |
| 209 | | ethernet-output | |
| 210 | | interface-output | |
| 211 | | ip4-drop | |
| 212 | | ip4-local | |
| 213 | | ip4-multicast | |
| 214 | | ip4-output | |
| 215 | | ip4-punt | |
| 216 | | ip4-unicast | |
| 217 | | ip6-drop | |
| 218 | | ip6-local | |
| 219 | | ip6-multicast | |
| 220 | | ip6-output | |
| 221 | | ip6-punt | |
| 222 | | ip6-unicast | |
| 223 | | mpls-input | |
| 224 | | mpls-output | |
| 225 | | nsh-output | |