@@ -2167,6 +2167,108 @@ handle_bridge_port_priority(NetplanParser* npp, yaml_node_t* node, const char* k
21672167 return TRUE;
21682168}
21692169
2170+ static gboolean
2171+ handle_generic_vlans (yaml_document_t * doc , yaml_node_t * node , GArray * * entryptr , const void * data , GError * * error )
2172+ {
2173+ static regex_t re ;
2174+ static gboolean re_inited = FALSE;
2175+
2176+ if (!re_inited ) {
2177+ g_assert (regcomp (& re , "^([0-9]+)(-([0-9]+))?( (pvid))?( (untagged))?$" , REG_EXTENDED ) == 0 );
2178+ re_inited = TRUE;
2179+ }
2180+
2181+ for (yaml_node_item_t * i = node -> data .sequence .items .start ; i < node -> data .sequence .items .top ; i ++ ) {
2182+ g_autofree char * vlan = NULL ;
2183+ yaml_node_t * entry = yaml_document_get_node (doc , * i );
2184+ assert_type (entry , YAML_SCALAR_NODE );
2185+
2186+ vlan = g_strdup (scalar (entry ));
2187+
2188+ size_t maxGroups = 7 + 1 ;
2189+ regmatch_t groups [maxGroups ];
2190+ /* does it match the vlans= definition? */
2191+ if (regexec (& re , vlan , maxGroups , groups , 0 ) == 0 ) {
2192+ NetplanBridgeVlan * data = g_new0 (NetplanBridgeVlan , 1 );
2193+ for (unsigned g = 1 ; g < maxGroups ; g = g + 2 ) {
2194+ if (groups [g ].rm_so == (size_t )-1 )
2195+ continue ; // Invalid group
2196+
2197+ char cursorCopy [strlen (vlan ) + 1 ];
2198+ strcpy (cursorCopy , vlan );
2199+ cursorCopy [groups [g ].rm_eo ] = 0 ;
2200+ guint v = 0 ;
2201+ switch (g ) {
2202+ case 1 :
2203+ v = g_ascii_strtoull (cursorCopy + groups [g ].rm_so , NULL , 10 );
2204+ if (v < 1 || v > 4094 )
2205+ return yaml_error (node , error , "malformed vlan vid '%u', must be in range [1..4094]" , v );
2206+ data -> vid = v ;
2207+ break ;
2208+ case 3 :
2209+ v = g_ascii_strtoull (cursorCopy + groups [g ].rm_so , NULL , 10 );
2210+ if (v < 1 || v > 4094 )
2211+ return yaml_error (node , error , "malformed vlan vid '%u', must be in range [1..4094]" , v );
2212+ else if (v <= data -> vid )
2213+ return yaml_error (node , error , "malformed vlan vid range '%s': %u > %u!" , scalar (entry ), data -> vid , v );
2214+ data -> vid_to = v ;
2215+ break ;
2216+ case 5 :
2217+ data -> pvid = TRUE;
2218+ break ;
2219+ case 7 :
2220+ data -> untagged = TRUE;
2221+ break ;
2222+ default : g_assert_not_reached (); // LCOV_EXCL_LINE
2223+ }
2224+ }
2225+ if (!* entryptr )
2226+ * entryptr = g_array_new (FALSE, FALSE, sizeof (NetplanBridgeVlan * ));
2227+ g_array_append_val (* entryptr , data );
2228+ continue ;
2229+ }
2230+
2231+ return yaml_error (node , error , "malformed vlan '%s', must be: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]" , scalar (entry ));
2232+ }
2233+
2234+ return TRUE;
2235+ }
2236+
2237+ static gboolean
2238+ handle_bridge_vlans (yaml_document_t * doc , yaml_node_t * node , const void * data , GError * * error )
2239+ {
2240+ return handle_generic_vlans (doc , node , & (cur_netdef -> bridge_params .vlans ), data , error );
2241+ }
2242+
2243+ static gboolean
2244+ handle_bridge_port_vlans (yaml_document_t * doc , yaml_node_t * node , const void * data , GError * * error )
2245+ {
2246+ for (yaml_node_pair_t * entry = node -> data .mapping .pairs .start ; entry < node -> data .mapping .pairs .top ; entry ++ ) {
2247+ yaml_node_t * key , * value ;
2248+ NetplanNetDefinition * component ;
2249+ GArray * * ref_ptr ;
2250+
2251+ key = yaml_document_get_node (doc , entry -> key );
2252+ assert_type (key , YAML_SCALAR_NODE );
2253+ value = yaml_document_get_node (doc , entry -> value );
2254+ assert_type (value , YAML_SEQUENCE_NODE );
2255+
2256+ component = g_hash_table_lookup (netdefs , scalar (key ));
2257+ if (!component ) {
2258+ add_missing_node (key );
2259+ } else {
2260+ ref_ptr = & (component -> bridge_params .port_vlans );
2261+ if (* ref_ptr )
2262+ return yaml_error (node , error , "%s: interface '%s' already has port vlans" ,
2263+ cur_netdef -> id , scalar (key ));
2264+
2265+ if (!handle_generic_vlans (doc , value , ref_ptr , data , error ))
2266+ return FALSE;
2267+ }
2268+ }
2269+ return TRUE;
2270+ }
2271+
21702272static const mapping_entry_handler bridge_params_handlers [] = {
21712273 {"ageing-time" , YAML_SCALAR_NODE , {.generic = handle_netdef_str }, netdef_offset (bridge_params .ageing_time )},
21722274 {"aging-time" , YAML_SCALAR_NODE , {.generic = handle_netdef_str }, netdef_offset (bridge_params .ageing_time )},
@@ -2175,8 +2277,10 @@ static const mapping_entry_handler bridge_params_handlers[] = {
21752277 {"max-age" , YAML_SCALAR_NODE , {.generic = handle_netdef_str }, netdef_offset (bridge_params .max_age )},
21762278 {"path-cost" , YAML_MAPPING_NODE , {.map = {.custom = handle_bridge_path_cost }}, netdef_offset (bridge_params .path_cost )},
21772279 {"port-priority" , YAML_MAPPING_NODE , {.map = {.custom = handle_bridge_port_priority }}, netdef_offset (bridge_params .port_priority )},
2280+ {"port-vlans" , YAML_MAPPING_NODE , handle_bridge_port_vlans },
21782281 {"priority" , YAML_SCALAR_NODE , {.generic = handle_netdef_guint }, netdef_offset (bridge_params .priority )},
21792282 {"stp" , YAML_SCALAR_NODE , {.generic = handle_netdef_bool }, netdef_offset (bridge_params .stp )},
2283+ {"vlans" , YAML_SEQUENCE_NODE , handle_bridge_vlans },
21802284 {NULL }
21812285};
21822286
0 commit comments