]>
Commit | Line | Data |
---|---|---|
774ebb6d QY |
1 | .. _vtysh: |
2 | ||
3 | ***** | |
4 | VTYSH | |
5 | ***** | |
6 | ||
7 | .. seealso:: :ref:`command-line-interface` | |
8 | ||
9 | .. _vtysh-architecture: | |
10 | ||
11 | Architecture | |
12 | ============ | |
13 | ||
14 | VTYSH is a shell for FRR daemons. It amalgamates all the CLI commands defined | |
15 | in each of the daemons and presents them to the user in a single shell, which | |
16 | saves the user from having to telnet to each of the daemons and use their | |
17 | individual shells. The amalgamation is achieved by | |
18 | :ref:`extracting <vtysh-command-extraction>` commands from daemons and | |
19 | injecting them into VTYSH at build time. | |
20 | ||
21 | At runtime, VTYSH maintains an instance of a CLI mode tree just like each | |
22 | daemon. However, the mode tree in VTYSH contains (almost) all commands from | |
23 | every daemon in the same tree, whereas individual daemons have trees that only | |
24 | contain commands relevant to themselves. VTYSH also uses the library CLI | |
25 | facilities to maintain the user's current position in the tree (the current | |
26 | node). Note that this position must be synchronized with all daemons; if a | |
27 | daemon receives a command that causes it to change its current node, VTYSH must | |
28 | also change its node. Since the extraction script does not understand the | |
29 | handler code of commands, but only their definitions, this and other behaviors | |
30 | must be manually programmed into VTYSH for every case where the internal state | |
31 | of VTYSH must change in response to a command. Details on how this is done are | |
32 | discussed in the :ref:`vtysh-special-defuns` section. | |
33 | ||
34 | VTYSH also handles writing and applying the integrated configuration file, | |
35 | :file:`/etc/frr/frr.conf`. Since it has knowledge of the entire command space | |
36 | of FRR, it can intelligently distribute configuration commands only to the | |
37 | daemons that understand them. Similarly, when writing the configuration file it | |
38 | takes care of combining multiple instances of configuration blocks and | |
39 | simplifying the output. This is discussed in :ref:`vtysh-configuration`. | |
40 | ||
41 | .. _vtysh-command-extraction: | |
42 | ||
43 | Command Extraction | |
44 | ------------------ | |
45 | ||
56f0bea7 | 46 | When VTYSH is built, a Perl script named :file:`extract.pl` searches the FRR |
774ebb6d QY |
47 | codebase looking for ``DEFUN``'s. It extracts these ``DEFUN``'s, transforms |
48 | them into ``DEFSH``'s and appends them to ``vtysh_cmd.c``. Each ``DEFSH`` | |
49 | contains the name of the command plus ``_vtysh``, as well as a flag that | |
50 | indicates which daemons the command was found in. When the command is executed | |
51 | in VTYSH, this flag is inspected to determine which daemons to send the command | |
52 | to. This way, commands are only sent to the daemons that know about them, | |
53 | avoiding spurious errors from daemons that don't have the command defined. | |
54 | ||
55 | The extraction script contains lots of hardcoded knowledge about what sources | |
56 | to look at and what flags to use for certain commands. | |
57 | ||
58 | .. _vtysh-special-defuns: | |
59 | ||
60 | Special DEFUNs | |
61 | -------------- | |
62 | ||
63 | In addition to the vanilla ``DEFUN`` macro for defining CLI commands, there are | |
64 | several VTYSH-specific ``DEFUN`` variants that each serve different purposes. | |
65 | ||
66 | ``DEFSH`` | |
67 | Used almost exclusively by generated VTYSH code. This macro defines a | |
68 | ``cmd_element`` with no handler function; the command, when executed, is | |
69 | simply forwarded to the daemons indicated in the daemon flag. | |
70 | ||
71 | ``DEFUN_NOSH`` | |
72 | Used by daemons. Has the same expansion as a ``DEFUN``, but ``extract.pl`` | |
73 | will skip these definitions when extracting commands. This is typically used | |
74 | when VTYSH must take some special action upon receiving the command, and the | |
75 | programmer therefore needs to write VTYSH's copy of the command manually | |
76 | instead of using the generated version. | |
77 | ||
78 | ``DEFUNSH`` | |
79 | The same as ``DEFUN``, but with an argument that allows specifying the | |
80 | ``->daemon`` field of the generated ``cmd_element``. This is used by VTYSH | |
81 | to determine which daemons to send the command to. | |
82 | ||
83 | ``DEFUNSH_ATTR`` | |
84 | A version of ``DEFUNSH`` that allows setting the ``->attr`` field of the | |
85 | generated ``cmd_element``. Not used in practice. | |
86 | ||
87 | .. _vtysh-configuration: | |
88 | ||
89 | Configuration Management | |
90 | ------------------------ | |
91 | ||
92 | When integrated configuration is used, VTYSH manages writing, reading and | |
93 | applying the FRR configuration file. VTYSH can be made to read and apply an | |
94 | integrated configuration to all running daemons by launching it with ``-f | |
95 | <file>``. It sends the appropriate configuration lines to the relevant daemons | |
96 | in the same way that commands entered by the user on VTYSH's shell prompt are | |
97 | processed. | |
98 | ||
99 | Configuration writing is more complicated. VTYSH makes a best-effort attempt to | |
100 | combine and simplify the configuration as much as possible. A working example | |
101 | is best to explain this behavior. | |
102 | ||
103 | Example | |
104 | ^^^^^^^ | |
105 | ||
106 | Suppose we have just *staticd* and *zebra* running on the system, and use VTYSH | |
107 | to apply the following configuration snippet: | |
108 | ||
109 | .. code-block:: frr | |
110 | ||
111 | ! | |
112 | vrf blue | |
113 | ip protocol static route-map ExampleRoutemap | |
114 | ip route 192.168.0.0/24 192.168.0.1 | |
115 | exit-vrf | |
116 | ! | |
117 | ||
118 | Note that *staticd* defines static route commands and *zebra* defines ``ip | |
119 | protocol`` commands. Therefore if we ask only *zebra* for its configuration, we | |
120 | get the following:: | |
121 | ||
122 | (config)# do sh running-config zebra | |
123 | Building configuration... | |
124 | ||
125 | ... | |
126 | ! | |
127 | vrf blue | |
128 | ip protocol static route-map ExampleRoutemap | |
129 | exit-vrf | |
130 | ! | |
131 | ... | |
132 | ||
133 | Note that the static route doesn't show up there. Similarly, if we ask | |
503efc38 | 134 | *staticd* for its configuration, we get:: |
774ebb6d QY |
135 | |
136 | (config)# do sh running-config staticd | |
137 | ||
138 | ... | |
139 | ! | |
140 | vrf blue | |
141 | ip route 192.168.0.0/24 192.168.0.1 | |
142 | exit-vrf | |
143 | ! | |
144 | ... | |
145 | ||
146 | But when we display the configuration with VTYSH, we see:: | |
147 | ||
148 | ubuntu-bionic(config)# do sh running-config | |
149 | ||
150 | ... | |
151 | ! | |
152 | vrf blue | |
153 | ip protocol static route-map ExampleRoutemap | |
154 | ip route 192.168.0.0/24 192.168.0.1 | |
155 | exit-vrf | |
156 | ! | |
157 | ... | |
158 | ||
159 | This is because VTYSH asks each daemon for its currently running configuration, | |
160 | and combines equivalent blocks together. In the above example, it combined the | |
161 | ``vrf blue`` blocks from both *zebra* and *staticd* together into one. This is | |
162 | done in :file:`vtysh_config.c`. | |
503efc38 QY |
163 | |
164 | Protocol | |
165 | ======== | |
166 | ||
167 | VTYSH communicates with FRR daemons by way of domain socket. Each daemon | |
168 | creates its own socket, typically in :file:`/var/run/frr/<daemon>.vty`. The | |
169 | protocol is very simple. In the VTYSH to daemon direction, messages are simply | |
56f0bea7 | 170 | NUL-terminated strings, whose content are CLI commands. Here is a typical |
503efc38 QY |
171 | message from VTYSH to a daemon: |
172 | ||
173 | :: | |
174 | ||
175 | Request | |
176 | ||
177 | 00000000: 646f 2077 7269 7465 2074 6572 6d69 6e61 do write termina | |
178 | 00000010: 6c0a 00 l.. | |
179 | ||
180 | ||
56f0bea7 | 181 | The response format has some more data in it. First is a NUL-terminated string |
503efc38 QY |
182 | containing the plaintext response, which is just the output of the command that |
183 | was sent in the request. This is displayed to the user. The plaintext response | |
184 | is followed by 3 null marker bytes, followed by a 1-byte status code that | |
185 | indicates whether the command was successful or not. | |
186 | ||
187 | :: | |
188 | ||
189 | Response | |
190 | ||
191 | 0 1 2 3 | |
192 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
193 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
194 | | Plaintext Response | | |
195 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
196 | | Marker (0x00) | Status Code | | |
197 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
198 | ||
199 | ||
200 | The first ``0x00`` byte in the marker also serves to terminate the plaintext | |
201 | response. |