User Tools

Site Tools


cli_entry

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cli_entry [2009/06/13 19:31] andreicli_entry [2009/06/13 20:31] (current) andrei
Line 5: Line 5:
 == Step 1 : setting up protocol information == == Step 1 : setting up protocol information ==
  
-Most protocols have a small number of configurable parameters that influence the protocol's behaviour. Naturally, we'll want to store these parameters' values somewhere. LiSA stores all such information in a shared memory structure that is protected from concurrent accesses. So the first step is to define our own structure that contains protocol-specific data. Since all we want to do is enable the protocol, our structure will only have a field called enabled. We'll create a header file called **rstp_client.h** in the **userspace/include/** folder where we'll keep CLI-interaction related information. We have to include this header in **include/shared.h** so our structure will be recognized. In this header file we add the following:+Most protocols have a small number of configurable parameters that influence the protocol's behaviour. Naturally, we'll want to store these parameters' values somewhere. LiSA stores all such information in a shared memory structure that is protected from concurrent accesses. So the first step is to define our own structure that contains protocol-specific data. Since all we want to do is enable the protocol, our structure will only have a field called enabled. We'll create a header file called **rstp_client.h** in the **include/** folder where we'll keep CLI-interaction related information. We have to include this header in **include/shared.h** so our structure will be recognized. In this header file we add the following:
 <code c> <code c>
 struct rstp_configuration { struct rstp_configuration {
Line 56: Line 56:
 == Step 2 : adding menu entries for global RSTP support == == Step 2 : adding menu entries for global RSTP support ==
  
-== Step : adding menu entries for enabling RSTP on a specific interface ==+Creating menu entries requires adding struct menu_node fields to the existing menu structure. Adding a global option for enabling RSTP means adding the following code to the config_main structure found in **cli/menu/config.c** 
 +<code c> 
 +struct menu_node config_main = { 
 +  /* Root node, .name is used as prompt */ 
 +  .name     = "config", 
 +  .subtree  = (struct menu_node *[]) { 
 +    /* #rstp */ 
 +    & (struct menu_node){ 
 +      .name     = "rstp", 
 +      .help     = "Global RSTP configuration subcommands", 
 +      .mask     = CLI_MASK(PRIV(15)), 
 +      .tokenize = NULL, 
 +      .run      = NULL, 
 +      .subtree  = (struct menu_node *[]) { /*{{{*/ 
 +        /* #cdp run */ 
 +        & (struct menu_node){ 
 +          .name     = "run", 
 +          .help     = "", 
 +          .mask     = CLI_MASK(PRIV(15)), 
 +          .tokenize = NULL, 
 +          .run      = cmd_rstp_run, 
 +          .subtree  = NULL 
 +        }, 
 + 
 +        NULL 
 +      } /*}}}*/ 
 +    }, 
 +    //... 
 +</code> 
 + 
 +Also, add an option for disabling RSTP on the switch. This is done Cisco-like by adding //no// in front of the option. So basically we add an entry in the //no// subtree. 
 +<code c> 
 +  /* #no */ 
 +    & (struct menu_node){ 
 +      .name     = "no", 
 +      .help     = "Negate a command or set its defaults", 
 +      .mask     = CLI_MASK(PRIV(15)), 
 +      .tokenize = NULL, 
 +      .run      = NULL, 
 +      .subtree  = (struct menu_node *[]) { /*{{{*/ 
 +        /* #no rstp */ 
 +        & (struct menu_node){ 
 +          .name     = "rstp", 
 +          .help     = "Global RSTP configuration subcommands", 
 +          .mask     = CLI_MASK(PRIV(15)), 
 +          .tokenize = NULL, 
 +          .run      = NULL, 
 +          .subtree  = (struct menu_node *[]) { /*{{{*/ 
 +            /* #no rstp run */ 
 +            & (struct menu_node){ 
 +              .name     = "run", 
 +              .help     = "", 
 +              .mask     = CLI_MASK(PRIV(15)), 
 +              .tokenize = NULL, 
 +              .run      = cmd_rstp_run, 
 +              .subtree  = NULL 
 +            }, 
 + 
 +            NULL 
 +          } /*}}}*/ 
 +        }, 
 +    //... 
 +</code> 
 + 
 +The position of the entry in the code reflects its position in the actual menu. That is, if the first entry in the subtree of config_main is the struct menu_node rstp then it will also be the first entry in the CLI menu. Notice than when one of the entries is selected then the cmd_rstp_run routine is called. 
 + 
 +== Step 3: implementing the global RSTP enable routine == 
 + 
 +The //run// field from struct menu_node represents a pointer to a function having the following signature : int (struct cli_context *, int, char **, struct menu_node **). For a detailed description see the struct menu_node definition in **cli/cli.h**. So, first thing to do is define a routine called cmp_rstp_run having this signature in the **cli/command/config_if.h** header. 
 + 
 +The routine's implementation will reside in **cli/command/config_if.c**. It gets the rstp_configuration data we previously defined and sets/resets the enabled field according to the given option. It then writes the configuration back in the shared mem. 
 +<code c> 
 +int cmd_rstp_run(struct cli_context *ctx, int argc, char **argv, struct menu_node **nodev) 
 +
 +    struct rstp_configuration rstp; 
 +    int enabled = 1; 
 + 
 +    if (!strcmp(nodev[0]->name, "no")) 
 +            enabled = 0; 
 +    shared_get_rstp(&rstp); 
 +    rstp.enabled = enabled; 
 +    shared_set_rstp(&rstp); 
 + 
 +    return CLI_EX_OK; 
 +
 +</code> 
 + 
 +== Step : adding menu entries for enabling RSTP on a specific interface ==
  
 Now that we have the protocol infrastructure in place, we can add menu entries for enabling RSTP on a certain interface. We want the menu entry to be available only for the selected interface. Only after we've given the commands //conf t// and //int EthX// should the entry become available. So we have to edit the **cli/menu/config_if.c** file, because that's where interface-related commands are. To add the enable option to the menu, we add this to the mentioned file: Now that we have the protocol infrastructure in place, we can add menu entries for enabling RSTP on a certain interface. We want the menu entry to be available only for the selected interface. Only after we've given the commands //conf t// and //int EthX// should the entry become available. So we have to edit the **cli/menu/config_if.c** file, because that's where interface-related commands are. To add the enable option to the menu, we add this to the mentioned file:
Line 128: Line 215:
 Notice that the routine called when the entries are selected is cmd_rstp_if_set. So... Notice that the routine called when the entries are selected is cmd_rstp_if_set. So...
  
-== Step : implementing called routine ==+== Step : implementing the interface enable/disable routine ==
  
-The //run// field from struct menu_node represents pointer to a function having the following signature : int (struct cli_context *, int, char **, struct menu_node **). For detailed description see the struct menu_node definition in **cli/cli.h**So, first thing to do is define routine called cmp_rstp_if_set having this signature in the **cli/command/config_if.h** header. +The cmd_rstp_if_set routine's job is to send message to the daemon implementing the protocol that it wants specific interface to be enabled/disabledThis requires an interprocess communication mechanism between the daemon and the CLI processIt involves the daemon creating thread specifically for this task. The details are not related to the menu entries so they won't be described here.
- +
-The routine's implementation will reside in **cli/command/config_if.c**: +
-<code c> +
-int cmd_rstp_if_set(struct cli_context *ctx, int argc, char **argv, struct menu_node **nodev) +
-+
-    struct rstp_session *rstp; +
-    struct rstp_configuration cfg; +
-    struct swcli_context *uc = SWCLI_CTX(ctx); +
-    int enable = 1; +
-    int err; +
- +
-    shared_get_rstp(&cfg); +
-    if (!cfg.enabled) +
-            return 0; +
- +
-    if (!strcmp(nodev[0]->name, "no")) +
-            enable = 0; +
- +
-    if (!RSTP_SESSION_OPEN(ctx, rstp)) { +
-            EX_STATUS_REASON(ctx, "%s", strerror(errno)); +
-            return CLI_EX_REJECTED; +
-    } +
-    err = rstp_set_interface(rstp, uc->ifindex, enable); +
-    RSTP_SESSION_CLOSE(ctx, rstp); +
- +
-    return err; +
-+
-</code>+
  
cli_entry.1244910701.txt.gz · Last modified: by andrei