2828
2929static const char * const netdev_kind_table [] = {
3030 [NETDEV_KIND_BRIDGE ] = "bridge" ,
31- [NETDEV_KIND_BOND ] = "bond"
31+ [NETDEV_KIND_BOND ] = "bond" ,
32+ [NETDEV_KIND_VLAN ] = "vlan" ,
3233};
3334
3435DEFINE_STRING_TABLE_LOOKUP (netdev_kind , NetdevKind );
@@ -154,13 +155,13 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
154155 return 1 ;
155156}
156157
157- static int netdev_create (Netdev * netdev ) {
158+ static int netdev_create (Netdev * netdev , Link * link , sd_rtnl_message_handler_t callback ) {
158159 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message * req = NULL ;
159160 const char * kind ;
160161 int r ;
161162
162163 assert (netdev );
163- assert (netdev -> state == _NETDEV_STATE_INVALID );
164+ assert (!( netdev -> kind == NETDEV_KIND_VLAN ) || ( link && callback && netdev -> vlanid >= 0 ) );
164165 assert (netdev -> name );
165166 assert (netdev -> manager );
166167 assert (netdev -> manager -> rtnl );
@@ -173,6 +174,16 @@ static int netdev_create(Netdev *netdev) {
173174 return r ;
174175 }
175176
177+ if (link ) {
178+ r = sd_rtnl_message_append_u32 (req , IFLA_LINK , link -> ifindex );
179+ if (r < 0 ) {
180+ log_error_netdev (netdev ,
181+ "Could not append IFLA_LINK attribute: %s" ,
182+ strerror (- r ));
183+ return r ;
184+ }
185+ }
186+
176187 r = sd_rtnl_message_append_string (req , IFLA_IFNAME , netdev -> name );
177188 if (r < 0 ) {
178189 log_error_netdev (netdev ,
@@ -203,6 +214,32 @@ static int netdev_create(Netdev *netdev) {
203214 return r ;
204215 }
205216
217+ if (netdev -> vlanid >= 0 ) {
218+ r = sd_rtnl_message_open_container (req , IFLA_INFO_DATA );
219+ if (r < 0 ) {
220+ log_error_netdev (netdev ,
221+ "Could not open IFLA_INFO_DATA container: %s" ,
222+ strerror (- r ));
223+ return r ;
224+ }
225+
226+ r = sd_rtnl_message_append_u16 (req , IFLA_VLAN_ID , netdev -> vlanid );
227+ if (r < 0 ) {
228+ log_error_netdev (netdev ,
229+ "Could not append IFLA_VLAN_ID attribute: %s" ,
230+ strerror (- r ));
231+ return r ;
232+ }
233+
234+ r = sd_rtnl_message_close_container (req );
235+ if (r < 0 ) {
236+ log_error_netdev (netdev ,
237+ "Could not close IFLA_INFO_DATA container %s" ,
238+ strerror (- r ));
239+ return r ;
240+ }
241+ }
242+
206243 r = sd_rtnl_message_close_container (req );
207244 if (r < 0 ) {
208245 log_error_netdev (netdev ,
@@ -211,7 +248,10 @@ static int netdev_create(Netdev *netdev) {
211248 return r ;
212249 }
213250
214- r = sd_rtnl_call_async (netdev -> manager -> rtnl , req , & netdev_create_handler , netdev , 0 , NULL );
251+ if (link )
252+ r = sd_rtnl_call_async (netdev -> manager -> rtnl , req , callback , link , 0 , NULL );
253+ else
254+ r = sd_rtnl_call_async (netdev -> manager -> rtnl , req , & netdev_create_handler , netdev , 0 , NULL );
215255 if (r < 0 ) {
216256 log_error_netdev (netdev ,
217257 "Could not send rtnetlink message: %s" , strerror (- r ));
@@ -226,6 +266,9 @@ static int netdev_create(Netdev *netdev) {
226266}
227267
228268int netdev_enslave (Netdev * netdev , Link * link , sd_rtnl_message_handler_t callback ) {
269+ if (netdev -> kind == NETDEV_KIND_VLAN )
270+ return netdev_create (netdev , link , callback );
271+
229272 if (netdev -> state == NETDEV_STATE_READY ) {
230273 netdev_enslave_ready (netdev , link , callback );
231274 } else {
@@ -289,8 +332,9 @@ static int netdev_load_one(Manager *manager, const char *filename) {
289332 netdev -> manager = manager ;
290333 netdev -> state = _NETDEV_STATE_INVALID ;
291334 netdev -> kind = _NETDEV_KIND_INVALID ;
335+ netdev -> vlanid = -1 ;
292336
293- r = config_parse (NULL , filename , file , "Netdev\0" , config_item_perf_lookup ,
337+ r = config_parse (NULL , filename , file , "Netdev\0VLAN\ 0" , config_item_perf_lookup ,
294338 (void * ) network_gperf_lookup , false, false, netdev );
295339 if (r < 0 ) {
296340 log_warning ("Could not parse config file %s: %s" , filename , strerror (- r ));
@@ -307,6 +351,11 @@ static int netdev_load_one(Manager *manager, const char *filename) {
307351 return 0 ;
308352 }
309353
354+ if (netdev -> kind == NETDEV_KIND_VLAN && netdev -> vlanid < 0 ) {
355+ log_warning ("VLAN without Id configured in %s. Ignoring" , filename );
356+ return 0 ;
357+ }
358+
310359 netdev -> filename = strdup (filename );
311360 if (!netdev -> filename )
312361 return log_oom ();
@@ -317,9 +366,11 @@ static int netdev_load_one(Manager *manager, const char *filename) {
317366
318367 LIST_HEAD_INIT (netdev -> callbacks );
319368
320- r = netdev_create (netdev );
321- if (r < 0 )
322- return r ;
369+ if (netdev -> kind != NETDEV_KIND_VLAN ) {
370+ r = netdev_create (netdev , NULL , NULL );
371+ if (r < 0 )
372+ return r ;
373+ }
323374
324375 netdev = NULL ;
325376
0 commit comments