Browse Source

[settings] Make "netX" settings block function as a symbolic link

Add a facility for settings blocks to act as symbolic links to other
settings blocks, and reimplement the "netX" virtual settings block
using this facility.

The primary advantage of this approach is that unscoped settings such
as ${mac} and ${filename} will now reflect the settings obtained from
the most recently opened network device: in most cases, this will mean
the settings obtained from the most recent DHCP attempt.  This should
improve conformance to the principle of least astonishment.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
66ea458125
4 changed files with 107 additions and 24 deletions
  1. 50
    23
      src/core/settings.c
  2. 1
    1
      src/hci/tui/settings_ui.c
  3. 7
    0
      src/include/ipxe/settings.h
  4. 49
    0
      src/net/netdev_settings.c

+ 50
- 23
src/core/settings.c View File

271
 					const char *name ) {
271
 					const char *name ) {
272
 	struct settings *settings;
272
 	struct settings *settings;
273
 
273
 
274
+	/* Find target parent settings block */
275
+	parent = settings_target ( parent );
276
+
274
 	/* Treat empty name as meaning "this block" */
277
 	/* Treat empty name as meaning "this block" */
275
 	if ( ! *name )
278
 	if ( ! *name )
276
 		return parent;
279
 		return parent;
278
 	/* Look for child with matching name */
281
 	/* Look for child with matching name */
279
 	list_for_each_entry ( settings, &parent->children, siblings ) {
282
 	list_for_each_entry ( settings, &parent->children, siblings ) {
280
 		if ( strcmp ( settings->name, name ) == 0 )
283
 		if ( strcmp ( settings->name, name ) == 0 )
281
-			return settings;
284
+			return settings_target ( settings );
282
 	}
285
 	}
283
 
286
 
284
 	return NULL;
287
 	return NULL;
299
 	} *new_child;
302
 	} *new_child;
300
 	struct settings *settings;
303
 	struct settings *settings;
301
 
304
 
305
+	/* Find target parent settings block */
306
+	parent = settings_target ( parent );
307
+
302
 	/* Return existing settings, if existent */
308
 	/* Return existing settings, if existent */
303
 	if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
309
 	if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
304
 		return settings;
310
 		return settings;
330
 	static char buf[16];
336
 	static char buf[16];
331
 	char tmp[ sizeof ( buf ) ];
337
 	char tmp[ sizeof ( buf ) ];
332
 
338
 
339
+	/* Find target settings block */
340
+	settings = settings_target ( settings );
341
+
342
+	/* Construct name */
333
 	for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) {
343
 	for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) {
334
 		memcpy ( tmp, buf, sizeof ( tmp ) );
344
 		memcpy ( tmp, buf, sizeof ( tmp ) );
335
 		snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp );
345
 		snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp );
359
 
369
 
360
 	/* Parse each name component in turn */
370
 	/* Parse each name component in turn */
361
 	while ( remainder ) {
371
 	while ( remainder ) {
362
-		struct net_device *netdev;
363
-
364
 		subname = remainder;
372
 		subname = remainder;
365
 		remainder = strchr ( subname, '.' );
373
 		remainder = strchr ( subname, '.' );
366
 		if ( remainder )
374
 		if ( remainder )
367
 			*(remainder++) = '\0';
375
 			*(remainder++) = '\0';
368
-
369
-		/* Special case "netX" root settings block */
370
-		if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
371
-		     ( ( netdev = last_opened_netdev() ) != NULL ) )
372
-			settings = get_child ( settings, netdev->name );
373
-		else
374
-			settings = get_child ( settings, subname );
375
-
376
+		settings = get_child ( settings, subname );
376
 		if ( ! settings )
377
 		if ( ! settings )
377
 			break;
378
 			break;
378
 	}
379
 	}
460
 			const char *name ) {
461
 			const char *name ) {
461
 	struct settings *old_settings;
462
 	struct settings *old_settings;
462
 
463
 
463
-	/* NULL parent => add to settings root */
464
+	/* Sanity check */
464
 	assert ( settings != NULL );
465
 	assert ( settings != NULL );
465
-	if ( parent == NULL )
466
-		parent = &settings_root;
466
+
467
+	/* Find target parent settings block */
468
+	parent = settings_target ( parent );
467
 
469
 
468
 	/* Apply settings block name */
470
 	/* Apply settings block name */
469
 	settings->name = name;
471
 	settings->name = name;
523
  ******************************************************************************
525
  ******************************************************************************
524
  */
526
  */
525
 
527
 
528
+/**
529
+ * Redirect to target settings block
530
+ *
531
+ * @v settings		Settings block, or NULL
532
+ * @ret settings	Underlying settings block
533
+ */
534
+struct settings * settings_target ( struct settings *settings ) {
535
+
536
+	/* NULL settings implies the global settings root */
537
+	if ( ! settings )
538
+		settings = &settings_root;
539
+
540
+	/* Redirect to underlying settings block, if applicable */
541
+	if ( settings->op->redirect )
542
+		return settings->op->redirect ( settings );
543
+
544
+	/* Otherwise, return this settings block */
545
+	return settings;
546
+}
547
+
526
 /**
548
 /**
527
  * Check applicability of setting
549
  * Check applicability of setting
528
  *
550
  *
532
  */
554
  */
533
 int setting_applies ( struct settings *settings, struct setting *setting ) {
555
 int setting_applies ( struct settings *settings, struct setting *setting ) {
534
 
556
 
557
+	/* Find target settings block */
558
+	settings = settings_target ( settings );
559
+
560
+	/* Check applicability of setting */
535
 	return ( settings->op->applies ?
561
 	return ( settings->op->applies ?
536
 		 settings->op->applies ( settings, setting ) : 1 );
562
 		 settings->op->applies ( settings, setting ) : 1 );
537
 }
563
 }
549
 		    const void *data, size_t len ) {
575
 		    const void *data, size_t len ) {
550
 	int rc;
576
 	int rc;
551
 
577
 
552
-	/* NULL settings implies storing into the global settings root */
553
-	if ( ! settings )
554
-		settings = &settings_root;
578
+	/* Find target settings block */
579
+	settings = settings_target ( settings );
555
 
580
 
556
 	/* Fail if tag does not apply to this settings block */
581
 	/* Fail if tag does not apply to this settings block */
557
 	if ( ! setting_applies ( settings, setting ) )
582
 	if ( ! setting_applies ( settings, setting ) )
609
 	if ( origin )
634
 	if ( origin )
610
 		*origin = NULL;
635
 		*origin = NULL;
611
 
636
 
612
-	/* NULL settings implies starting at the global settings root */
613
-	if ( ! settings )
614
-		settings = &settings_root;
637
+	/* Find target settings block */
638
+	settings = settings_target ( settings );
615
 
639
 
616
 	/* Sanity check */
640
 	/* Sanity check */
617
 	if ( ! settings->op->fetch )
641
 	if ( ! settings->op->fetch )
971
  * @v settings		Settings block
995
  * @v settings		Settings block
972
  */
996
  */
973
 void clear_settings ( struct settings *settings ) {
997
 void clear_settings ( struct settings *settings ) {
998
+
999
+	/* Find target settings block */
1000
+	settings = settings_target ( settings );
1001
+
1002
+	/* Clear settings, if applicable */
974
 	if ( settings->op->clear )
1003
 	if ( settings->op->clear )
975
 		settings->op->clear ( settings );
1004
 		settings->op->clear ( settings );
976
 }
1005
 }
1230
 		   char *buf, size_t len ) {
1259
 		   char *buf, size_t len ) {
1231
 	const char *name;
1260
 	const char *name;
1232
 
1261
 
1233
-	if ( ! settings )
1234
-		settings = &settings_root;
1235
-
1262
+	settings = settings_target ( settings );
1236
 	name = settings_name ( settings );
1263
 	name = settings_name ( settings );
1237
 	return snprintf ( buf, len, "%s%s%s:%s", name, ( name[0] ? "/" : "" ),
1264
 	return snprintf ( buf, len, "%s%s%s:%s", name, ( name[0] ? "/" : "" ),
1238
 			  setting->name, setting->type->name );
1265
 			  setting->name, setting->type->name );

+ 1
- 1
src/hci/tui/settings_ui.c View File

441
 static void init_widget ( struct setting_widget *widget,
441
 static void init_widget ( struct setting_widget *widget,
442
 			  struct settings *settings ) {
442
 			  struct settings *settings ) {
443
 
443
 
444
-	widget->settings = settings;
444
+	widget->settings = settings_target ( settings );
445
 	widget->num_rows = select_setting_row ( widget, 0 );
445
 	widget->num_rows = select_setting_row ( widget, 0 );
446
 	widget->first_visible = SETTINGS_LIST_ROWS;
446
 	widget->first_visible = SETTINGS_LIST_ROWS;
447
 	draw_title_row ( widget );
447
 	draw_title_row ( widget );

+ 7
- 0
src/include/ipxe/settings.h View File

77
 
77
 
78
 /** Settings block operations */
78
 /** Settings block operations */
79
 struct settings_operations {
79
 struct settings_operations {
80
+	/** Redirect to underlying settings block (if applicable)
81
+	 *
82
+	 * @v settings		Settings block
83
+	 * @ret settings	Underlying settings block
84
+	 */
85
+	struct settings * ( * redirect ) ( struct settings *settings );
80
 	/** Check applicability of setting
86
 	/** Check applicability of setting
81
 	 *
87
 	 *
82
 	 * @v settings		Settings block
88
 	 * @v settings		Settings block
248
 			       struct settings *parent, const char *name );
254
 			       struct settings *parent, const char *name );
249
 extern void unregister_settings ( struct settings *settings );
255
 extern void unregister_settings ( struct settings *settings );
250
 
256
 
257
+extern struct settings * settings_target ( struct settings *settings );
251
 extern int setting_applies ( struct settings *settings,
258
 extern int setting_applies ( struct settings *settings,
252
 			     struct setting *setting );
259
 			     struct setting *setting );
253
 extern int store_setting ( struct settings *settings, struct setting *setting,
260
 extern int store_setting ( struct settings *settings, struct setting *setting,

+ 49
- 0
src/net/netdev_settings.c View File

27
 #include <ipxe/settings.h>
27
 #include <ipxe/settings.h>
28
 #include <ipxe/device.h>
28
 #include <ipxe/device.h>
29
 #include <ipxe/netdevice.h>
29
 #include <ipxe/netdevice.h>
30
+#include <ipxe/init.h>
30
 
31
 
31
 /** @file
32
 /** @file
32
  *
33
  *
295
 	.fetch = netdev_fetch,
296
 	.fetch = netdev_fetch,
296
 	.clear = netdev_clear,
297
 	.clear = netdev_clear,
297
 };
298
 };
299
+
300
+/**
301
+ * Redirect "netX" settings block
302
+ *
303
+ * @v settings		Settings block
304
+ * @ret settings	Underlying settings block
305
+ */
306
+static struct settings * netdev_redirect ( struct settings *settings ) {
307
+	struct net_device *netdev;
308
+
309
+	/* Redirect to most recently opened network device */
310
+	netdev = last_opened_netdev();
311
+	if ( netdev ) {
312
+		return netdev_settings ( netdev );
313
+	} else {
314
+		return settings;
315
+	}
316
+}
317
+
318
+/** "netX" settings operations */
319
+static struct settings_operations netdev_redirect_settings_operations = {
320
+	.redirect = netdev_redirect,
321
+};
322
+
323
+/** "netX" settings */
324
+static struct settings netdev_redirect_settings = {
325
+	.refcnt = NULL,
326
+	.siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
327
+	.children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
328
+	.op = &netdev_redirect_settings_operations,
329
+};
330
+
331
+/** Initialise "netX" settings */
332
+static void netdev_redirect_settings_init ( void ) {
333
+	int rc;
334
+
335
+	if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
336
+					"netX" ) ) != 0 ) {
337
+		DBG ( "Could not register netX settings: %s\n",
338
+		      strerror ( rc ) );
339
+		return;
340
+	}
341
+}
342
+
343
+/** "netX" settings initialiser */
344
+struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
345
+	.initialise = netdev_redirect_settings_init,
346
+};

Loading…
Cancel
Save