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 2 : 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 4 : 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 3 : implementing called routine ==+== Step 5 : implementing the interface enable/disable 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_if_set having this signature in the **cli/command/config_if.h** header. +The cmd_rstp_if_set routine's job is to send a message to the daemon implementing the protocol that it wants a specific interface to be enabled/disabled. This requires an interprocess communication mechanism between the daemon and the CLI process. It involves the daemon creating a 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