LCOV - code coverage report
Current view: top level - vnet/ip - ip6_link.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 157 268 58.6 %
Date: 2023-10-26 01:39:38 Functions: 31 39 79.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/ip/ip6_link.h>
      17             : #include <vnet/ip/ip6_ll_table.h>
      18             : 
      19             : #include <vnet/ethernet/ethernet.h>
      20             : #include <vnet/mfib/ip6_mfib.h>
      21             : #include <vnet/adj/adj_mcast.h>
      22             : 
      23             : typedef struct ip6_link_delegate_t_
      24             : {
      25             :   u32 ild_sw_if_index;
      26             :   ip6_link_delegate_id_t ild_type;
      27             :   index_t ild_index;
      28             : } ip6_link_delegate_t;
      29             : 
      30             : const static ip6_link_delegate_t ip6_link_delegate_uninit = {
      31             :   .ild_sw_if_index = ~0,
      32             : };
      33             : 
      34             : typedef struct ip6_link_t_
      35             : {
      36             :   /** interface ip6 is enabled on */
      37             :   u32 il_sw_if_index;
      38             : 
      39             :   /** link-local address - if unset that IP6 is disabled*/
      40             :   ip6_address_t il_ll_addr;
      41             : 
      42             :   /** list of delegates */
      43             :   ip6_link_delegate_t *il_delegates;
      44             : 
      45             :   /** multicast adjacency for this link */
      46             :   adj_index_t il_mcast_adj;
      47             : 
      48             :   /** number of references to IP6 enabled on this link */
      49             :   u32 il_locks;
      50             : } ip6_link_t;
      51             : 
      52             : #define FOREACH_IP6_LINK_DELEGATE(_ild, _il, body)      \
      53             : {                                                       \
      54             :  if (NULL != _il) {                                     \
      55             :    vec_foreach (_ild, _il->il_delegates) {              \
      56             :      if (ip6_link_delegate_is_init(_ild))               \
      57             :        body;                                            \
      58             :    }                                                    \
      59             :  }                                                      \
      60             : }
      61             : 
      62             : #define FOREACH_IP6_LINK_DELEGATE_ID(_id) \
      63             :   for (_id = 0; _id < il_delegate_id; _id++)
      64             : 
      65             : /** last used delegate ID */
      66             : static ip6_link_delegate_id_t il_delegate_id;
      67             : 
      68             : /** VFT registered per-delegate type */
      69             : static ip6_link_delegate_vft_t *il_delegate_vfts;
      70             : 
      71             : /** Per interface configs */
      72             : static ip6_link_t *ip6_links;
      73             : 
      74             : /** Randomizer */
      75             : static u64 il_randomizer;
      76             : 
      77             : /** Logging */
      78             : static vlib_log_class_t ip6_link_logger;
      79             : 
      80             : #define IP6_LINK_DBG(...)                       \
      81             :     vlib_log_debug (ip6_link_logger, __VA_ARGS__);
      82             : 
      83             : #define IP6_LINK_INFO(...)                              \
      84             :     vlib_log_notice (ip6_link_logger, __VA_ARGS__);
      85             : 
      86             : static bool
      87       33953 : ip6_link_delegate_is_init (const ip6_link_delegate_t * ild)
      88             : {
      89       33953 :   return (~0 != ild->ild_sw_if_index);
      90             : }
      91             : 
      92             : static bool
      93       29657 : ip6_link_is_enabled_i (const ip6_link_t * il)
      94             : {
      95       29657 :   return (!ip6_address_is_zero (&il->il_ll_addr));
      96             : }
      97             : 
      98             : static void
      99        1956 : ip6_link_local_address_from_mac (ip6_address_t * ip, const u8 * mac)
     100             : {
     101        1956 :   ip->as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL);
     102             :   /* Invert the "u" bit */
     103        1956 :   ip->as_u8[8] = mac[0] ^ (1 << 1);
     104        1956 :   ip->as_u8[9] = mac[1];
     105        1956 :   ip->as_u8[10] = mac[2];
     106        1956 :   ip->as_u8[11] = 0xFF;
     107        1956 :   ip->as_u8[12] = 0xFE;
     108        1956 :   ip->as_u8[13] = mac[3];
     109        1956 :   ip->as_u8[14] = mac[4];
     110        1956 :   ip->as_u8[15] = mac[5];
     111        1956 : }
     112             : 
     113             : static void
     114           0 : ip6_mac_address_from_link_local (u8 * mac, const ip6_address_t * ip)
     115             : {
     116             :   /* Invert the previously inverted "u" bit */
     117           0 :   mac[0] = ip->as_u8[8] ^ (1 << 1);
     118           0 :   mac[1] = ip->as_u8[9];
     119           0 :   mac[2] = ip->as_u8[10];
     120           0 :   mac[3] = ip->as_u8[13];
     121           0 :   mac[4] = ip->as_u8[14];
     122           0 :   mac[5] = ip->as_u8[15];
     123           0 : }
     124             : 
     125             : static ip6_link_t *
     126       34183 : ip6_link_get (u32 sw_if_index)
     127             : {
     128             :   ip6_link_t *il;
     129             : 
     130       34183 :   if (sw_if_index >= vec_len (ip6_links))
     131        4526 :     return (NULL);
     132             : 
     133       29657 :   il = &ip6_links[sw_if_index];
     134             : 
     135       29657 :   if (!ip6_link_is_enabled_i (il))
     136        1846 :     return (NULL);
     137             : 
     138       27811 :   return (il);
     139             : }
     140             : 
     141             : bool
     142         147 : ip6_link_is_enabled (u32 sw_if_index)
     143             : {
     144         147 :   return (NULL != ip6_link_get (sw_if_index));
     145             : }
     146             : 
     147             : 
     148             : int
     149        2164 : ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr)
     150             : {
     151             :   ip6_link_t *il;
     152             :   int rv;
     153             : 
     154        2164 :   il = ip6_link_get (sw_if_index);
     155             : 
     156        2164 :   if (NULL == il)
     157             :     {
     158             :       const vnet_sw_interface_t *sw_sup;
     159             :       const ethernet_interface_t *eth;
     160             :       vnet_main_t *vnm;
     161             : 
     162        2113 :       eth = NULL;
     163        2113 :       vnm = vnet_get_main ();
     164             : 
     165        2113 :       IP6_LINK_INFO ("enable: %U",
     166             :                      format_vnet_sw_if_index_name, vnm, sw_if_index);
     167             : 
     168        2113 :       sw_sup = vnet_get_sup_sw_interface (vnm, sw_if_index);
     169        2113 :       vec_validate (ip6_links, sw_if_index);
     170             : 
     171        2113 :       il = &ip6_links[sw_if_index];
     172        2113 :       il->il_locks = 0;
     173        2113 :       il->il_sw_if_index = sw_if_index;
     174        2113 :       il->il_mcast_adj = ADJ_INDEX_INVALID;
     175             : 
     176        2113 :       if (sw_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
     177        2113 :         eth = ethernet_get_interface (&ethernet_main, sw_sup->hw_if_index);
     178             : 
     179             :       /* use a user provided LL address if given */
     180        2113 :       if (NULL != link_local_addr)
     181           4 :         ip6_address_copy (&il->il_ll_addr, link_local_addr);
     182             : 
     183             :       /* generate from ethernet MAC */
     184        2113 :       if (ip6_address_is_zero (&il->il_ll_addr) && NULL != eth)
     185        1956 :         ip6_link_local_address_from_mac (&il->il_ll_addr,
     186        1956 :                                          eth->address.mac.bytes);
     187             : 
     188             :       /* choose a random address */
     189        2113 :       if (ip6_address_is_zero (&il->il_ll_addr))
     190             :         {
     191         153 :           il->il_ll_addr.as_u64[0] =
     192         153 :             clib_host_to_net_u64 (0xFE80000000000000ULL);
     193             : 
     194             :           /* make up an interface id */
     195         153 :           il->il_ll_addr.as_u64[1] = random_u64 (&il_randomizer);
     196             : 
     197             :           /* clear u bit */
     198         153 :           il->il_ll_addr.as_u8[8] &= 0xfd;
     199             :         }
     200             : 
     201             :       {
     202        2113 :         ip6_ll_prefix_t ilp = {
     203             :           .ilp_addr = il->il_ll_addr,
     204             :           .ilp_sw_if_index = sw_if_index,
     205             :         };
     206             : 
     207        2113 :         ip6_ll_table_entry_update (&ilp, FIB_ROUTE_PATH_LOCAL);
     208             :       }
     209             : 
     210             :       /* essentially "enables" ipv6 on this interface */
     211        2113 :       ip6_mfib_interface_enable_disable (sw_if_index, 1);
     212        2113 :       ip6_sw_interface_enable_disable (sw_if_index, 1);
     213             : 
     214             :       /* only ehternet interfaces support MLD and RA, which use the mcast adj
     215             :        */
     216        2113 :       if (NULL != eth)
     217        1958 :         il->il_mcast_adj =
     218        1958 :           adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, sw_if_index);
     219             : 
     220             :       /* inform all register clients */
     221             :       ip6_link_delegate_id_t id;
     222       10565 :       FOREACH_IP6_LINK_DELEGATE_ID (id)
     223             :       {
     224        8452 :         if (NULL != il_delegate_vfts[id].ildv_enable)
     225        8452 :           il_delegate_vfts[id].ildv_enable (il->il_sw_if_index);
     226             :       }
     227             : 
     228        2113 :       rv = 0;
     229             :     }
     230             :   else
     231             :     {
     232          51 :       rv = VNET_API_ERROR_VALUE_EXIST;
     233             :     }
     234             : 
     235        2164 :   il->il_locks++;
     236             : 
     237        2164 :   return (rv);
     238             : }
     239             : 
     240             : static void
     241        1941 : ip6_link_delegate_flush (ip6_link_t * il)
     242             : {
     243             :   ip6_link_delegate_t *ild;
     244             : 
     245             :   /* *INDENT-OFF* */
     246        9705 :   FOREACH_IP6_LINK_DELEGATE (ild, il,
     247             :   ({
     248             :     il_delegate_vfts[ild->ild_type].ildv_disable(ild->ild_index);
     249             :   }));
     250             :   /* *INDENT-ON* */
     251             : 
     252        1941 :   vec_free (il->il_delegates);
     253        1941 :   il->il_delegates = NULL;
     254        1941 : }
     255             : 
     256             : static void
     257        1941 : ip6_link_last_lock_gone (ip6_link_t * il)
     258             : {
     259        1941 :   ip6_ll_prefix_t ilp = {
     260             :     .ilp_addr = il->il_ll_addr,
     261        1941 :     .ilp_sw_if_index = il->il_sw_if_index,
     262             :   };
     263             : 
     264        1941 :   IP6_LINK_INFO ("last-lock: %U",
     265             :                  format_vnet_sw_if_index_name,
     266             :                  vnet_get_main (), il->il_sw_if_index);
     267             : 
     268        1941 :   ip6_link_delegate_flush (il);
     269        1941 :   ip6_ll_table_entry_delete (&ilp);
     270             : 
     271        1941 :   ip6_mfib_interface_enable_disable (il->il_sw_if_index, 0);
     272        1941 :   ip6_sw_interface_enable_disable (il->il_sw_if_index, 0);
     273             : 
     274        1941 :   ip6_address_set_zero (&il->il_ll_addr);
     275        1941 :   adj_unlock (il->il_mcast_adj);
     276        1941 :   il->il_mcast_adj = ADJ_INDEX_INVALID;
     277        1941 : }
     278             : 
     279             : static void
     280        1974 : ip6_link_unlock (ip6_link_t * il)
     281             : {
     282        1974 :   if (NULL == il)
     283           0 :     return;
     284             : 
     285        1974 :   il->il_locks--;
     286             : 
     287        1974 :   if (0 == il->il_locks)
     288        1939 :     ip6_link_last_lock_gone (il);
     289             : }
     290             : 
     291             : int
     292        1974 : ip6_link_disable (u32 sw_if_index)
     293             : {
     294             :   ip6_link_t *il;
     295             : 
     296        1974 :   il = ip6_link_get (sw_if_index);
     297             : 
     298        1974 :   if (NULL == il)
     299           0 :     return (VNET_API_ERROR_IP6_NOT_ENABLED);
     300             : 
     301        1974 :   IP6_LINK_INFO ("disable: %U",
     302             :                  format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index);
     303             : 
     304        1974 :   ip6_link_unlock (il);
     305             : 
     306        1974 :   return (0);
     307             : }
     308             : 
     309             : const ip6_address_t *
     310        1926 : ip6_get_link_local_address (u32 sw_if_index)
     311             : {
     312             :   const ip6_link_t *il;
     313             : 
     314        1926 :   il = ip6_link_get (sw_if_index);
     315             : 
     316        1926 :   if (NULL == il)
     317           0 :     return (NULL);
     318             : 
     319        1926 :   return (&il->il_ll_addr);
     320             : }
     321             : 
     322             : adj_index_t
     323        1893 : ip6_link_get_mcast_adj (u32 sw_if_index)
     324             : {
     325             :   const ip6_link_t *il;
     326             : 
     327        1893 :   il = ip6_link_get (sw_if_index);
     328             : 
     329        1893 :   if (NULL == il)
     330           0 :     return (INDEX_INVALID);
     331             : 
     332        1893 :   return (il->il_mcast_adj);
     333             : }
     334             : 
     335             : int
     336           7 : ip6_link_set_local_address (u32 sw_if_index, const ip6_address_t * address)
     337             : {
     338             :   ip6_link_delegate_t *ild;
     339             :   ip6_link_t *il;
     340             : 
     341           7 :   il = ip6_link_get (sw_if_index);
     342             : 
     343           7 :   if (NULL == il)
     344           4 :     return ip6_link_enable (sw_if_index, address);
     345             : 
     346           3 :   ip6_ll_prefix_t ilp = {
     347             :     .ilp_addr = il->il_ll_addr,
     348             :     .ilp_sw_if_index = sw_if_index,
     349             :   };
     350             : 
     351           3 :   IP6_LINK_INFO ("set-ll: %U -> %U",
     352             :                  format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index,
     353             :                  format_ip6_address, address);
     354             : 
     355           3 :   ip6_ll_table_entry_delete (&ilp);
     356           3 :   ip6_address_copy (&il->il_ll_addr, address);
     357           3 :   ip6_address_copy (&ilp.ilp_addr, address);
     358           3 :   ip6_ll_table_entry_update (&ilp, FIB_ROUTE_PATH_LOCAL);
     359             : 
     360             :   /* *INDENT-OFF* */
     361          15 :   FOREACH_IP6_LINK_DELEGATE (ild, il,
     362             :   ({
     363             :     if (NULL != il_delegate_vfts[ild->ild_type].ildv_ll_change)
     364             :       il_delegate_vfts[ild->ild_type].ildv_ll_change(ild->ild_index,
     365             :                                                      &il->il_ll_addr);
     366             :   }));
     367             :   /* *INDENT-ON* */
     368             : 
     369           3 :   return (0);
     370             : }
     371             : 
     372             : ip6_link_delegate_id_t
     373        2300 : ip6_link_delegate_register (const ip6_link_delegate_vft_t * vft)
     374             : {
     375        2300 :   ip6_link_delegate_id_t rc = il_delegate_id++;
     376             : 
     377        2300 :   ASSERT (vft->ildv_disable);
     378             : 
     379        2300 :   vec_validate (il_delegate_vfts, rc);
     380             : 
     381        2300 :   il_delegate_vfts[rc] = *vft;
     382             : 
     383        2300 :   return (rc);
     384             : }
     385             : 
     386             : index_t
     387        9719 : ip6_link_delegate_get (u32 sw_if_index, ip6_link_delegate_id_t id)
     388             : {
     389             :   ip6_link_t *il;
     390             : 
     391        9719 :   il = ip6_link_get (sw_if_index);
     392             : 
     393        9719 :   if (NULL == il)
     394           2 :     return (INDEX_INVALID);
     395             : 
     396       15591 :   vec_validate_init_empty (il->il_delegates, id, ip6_link_delegate_uninit);
     397             : 
     398        9717 :   if (!ip6_link_delegate_is_init (&il->il_delegates[id]))
     399        5874 :     return (INDEX_INVALID);
     400             : 
     401        3843 :   return (il->il_delegates[id].ild_index);
     402             : }
     403             : 
     404             : bool
     405        7987 : ip6_link_delegate_update (u32 sw_if_index,
     406             :                           ip6_link_delegate_id_t id, index_t ii)
     407             : {
     408             :   ip6_link_t *il;
     409             : 
     410        7987 :   il = ip6_link_get (sw_if_index);
     411             : 
     412        7987 :   if (NULL == il)
     413           0 :     return (false);
     414             : 
     415       10565 :   vec_validate_init_empty (il->il_delegates, id, ip6_link_delegate_uninit);
     416             : 
     417        7987 :   il->il_delegates[id].ild_sw_if_index = sw_if_index;
     418        7987 :   il->il_delegates[id].ild_type = id;
     419        7987 :   il->il_delegates[id].ild_index = ii;
     420             : 
     421        7987 :   return (true);
     422             : }
     423             : 
     424             : void
     425           0 : ip6_link_delegate_remove (u32 sw_if_index,
     426             :                           ip6_link_delegate_id_t id, index_t ii)
     427             : {
     428             :   ip6_link_t *il;
     429             : 
     430           0 :   il = ip6_link_get (sw_if_index);
     431             : 
     432           0 :   if (NULL != il)
     433             :     {
     434           0 :       if (vec_len (il->il_delegates) > id)
     435             :         {
     436           0 :           clib_memcpy (&il->il_delegates[id],
     437             :                        &ip6_link_delegate_uninit,
     438             :                        sizeof (il->il_delegates[0]));
     439             :         }
     440             :     }
     441           0 : }
     442             : 
     443             : static void
     444        4115 : ip6_link_add_del_address (ip6_main_t * im,
     445             :                           uword opaque,
     446             :                           u32 sw_if_index,
     447             :                           ip6_address_t * address,
     448             :                           u32 address_length,
     449             :                           u32 if_address_index, u32 is_delete)
     450             : {
     451             :   const ip6_link_delegate_t *ild;
     452             :   ip6_link_t *il;
     453             : 
     454        4115 :   if (ip6_address_is_link_local_unicast (address))
     455             :     // only interested in global addresses here
     456           0 :     return;
     457             : 
     458        4115 :   IP6_LINK_INFO ("addr-%s: %U -> %U",
     459             :                  (is_delete ? "del" : "add"),
     460             :                  format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index,
     461             :                  format_ip6_address, address);
     462             : 
     463        4115 :   il = ip6_link_get (sw_if_index);
     464             : 
     465        4115 :   if (NULL == il)
     466           0 :     return;
     467             : 
     468             :   /* *INDENT-OFF* */
     469       20575 :   FOREACH_IP6_LINK_DELEGATE (ild, il,
     470             :   ({
     471             :       if (is_delete)
     472             :         {
     473             :           if (NULL != il_delegate_vfts[ild->ild_type].ildv_addr_del)
     474             :             il_delegate_vfts[ild->ild_type].ildv_addr_del(ild->ild_index,
     475             :                                                           address, address_length);
     476             :         }
     477             :       else
     478             :         {
     479             :           if (NULL != il_delegate_vfts[ild->ild_type].ildv_addr_add)
     480             :             il_delegate_vfts[ild->ild_type].ildv_addr_add(ild->ild_index,
     481             :                                                           address, address_length);
     482             :         }
     483             :   }));
     484             :   /* *INDENT-ON* */
     485             : }
     486             : 
     487             : static clib_error_t *
     488       11798 : ip6_link_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
     489             : {
     490       11798 :   if (!is_add)
     491             :     {
     492             :       ip6_link_t *il;
     493             : 
     494        4251 :       il = ip6_link_get (sw_if_index);
     495             : 
     496        4251 :       IP6_LINK_DBG ("link-del: %U",
     497             :                     format_vnet_sw_if_index_name, vnet_get_main (),
     498             :                     sw_if_index);
     499             : 
     500        4251 :       if (NULL != il)
     501             :         /* force cleanup */
     502           2 :         ip6_link_last_lock_gone (il);
     503             :     }
     504             : 
     505       11798 :   return (NULL);
     506             : }
     507             : 
     508        3459 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip6_link_interface_add_del);
     509             : 
     510             : static clib_error_t *
     511         575 : ip6_link_init (vlib_main_t * vm)
     512             : {
     513         575 :   il_randomizer = clib_cpu_time_now ();
     514         575 :   ip6_link_logger = vlib_log_register_class ("ip6", "link");
     515             : 
     516             :   {
     517         575 :     ip6_add_del_interface_address_callback_t cb = {
     518             :       .function = ip6_link_add_del_address,
     519             :     };
     520         575 :     vec_add1 (ip6_main.add_del_interface_address_callbacks, cb);
     521             :   }
     522         575 :   return (NULL);
     523             : }
     524             : 
     525       42623 : VLIB_INIT_FUNCTION (ip6_link_init);
     526             : 
     527             : 
     528             : static clib_error_t *
     529           0 : test_ip6_link_command_fn (vlib_main_t * vm,
     530             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     531             : {
     532             :   u8 mac[6];
     533           0 :   ip6_address_t _a, *a = &_a;
     534             : 
     535           0 :   if (unformat (input, "%U", unformat_ethernet_address, mac))
     536             :     {
     537           0 :       ip6_link_local_address_from_mac (a, mac);
     538           0 :       vlib_cli_output (vm, "Link local address: %U", format_ip6_address, a);
     539           0 :       ip6_mac_address_from_link_local (mac, a);
     540           0 :       vlib_cli_output (vm, "Original MAC address: %U",
     541             :                        format_ethernet_address, mac);
     542             :     }
     543             : 
     544           0 :   return 0;
     545             : }
     546             : 
     547             : /*?
     548             :  * This command converts the given MAC Address into an IPv6 link-local
     549             :  * address.
     550             :  *
     551             :  * @cliexpar
     552             :  * Example of how to create an IPv6 link-local address:
     553             :  * @cliexstart{test ip6 link 16:d9:e0:91:79:86}
     554             :  * Link local address: fe80::14d9:e0ff:fe91:7986
     555             :  * Original MAC address: 16:d9:e0:91:79:86
     556             :  * @cliexend
     557             : ?*/
     558             : /* *INDENT-OFF* */
     559      285289 : VLIB_CLI_COMMAND (test_link_command, static) =
     560             : {
     561             :   .path = "test ip6 link",
     562             :   .function = test_ip6_link_command_fn,
     563             :   .short_help = "test ip6 link <mac-address>",
     564             : };
     565             : /* *INDENT-ON* */
     566             : 
     567             : static u8 *
     568           0 : ip6_print_addrs (u8 * s, u32 * addrs)
     569             : {
     570           0 :   ip_lookup_main_t *lm = &ip6_main.lookup_main;
     571             :   u32 i;
     572             : 
     573           0 :   for (i = 0; i < vec_len (addrs); i++)
     574             :     {
     575           0 :       ip_interface_address_t *a =
     576           0 :         pool_elt_at_index (lm->if_address_pool, addrs[i]);
     577           0 :       ip6_address_t *address = ip_interface_address_get_address (lm, a);
     578             : 
     579           0 :       s = format (s, "%U%U/%d\n",
     580             :                   format_white_space, 4,
     581           0 :                   format_ip6_address, address, a->address_length);
     582             :     }
     583             : 
     584           0 :   return (s);
     585             : }
     586             : 
     587             : static u8 *
     588           0 : format_ip6_link (u8 * s, va_list * arg)
     589             : {
     590           0 :   const ip6_link_t *il = va_arg (*arg, ip6_link_t *);
     591           0 :   ip_lookup_main_t *lm = &ip6_main.lookup_main;
     592           0 :   vnet_main_t *vnm = vnet_get_main ();
     593             : 
     594           0 :   if (!ip6_link_is_enabled_i (il))
     595           0 :     return (s);
     596             : 
     597           0 :   s = format (s, "%U is admin %s\n",
     598             :               format_vnet_sw_interface_name, vnm,
     599             :               vnet_get_sw_interface (vnm, il->il_sw_if_index),
     600           0 :               (vnet_sw_interface_is_admin_up (vnm, il->il_sw_if_index) ?
     601             :                "up" : "down"));
     602             : 
     603             :   u32 ai;
     604           0 :   u32 *link_scope = 0, *global_scope = 0;
     605           0 :   u32 *local_scope = 0, *unknown_scope = 0;
     606             :   ip_interface_address_t *a;
     607             :   const ip6_link_delegate_t *ild;
     608             : 
     609           0 :   vec_validate_init_empty (lm->if_address_pool_index_by_sw_if_index,
     610             :                            il->il_sw_if_index, ~0);
     611           0 :   ai = lm->if_address_pool_index_by_sw_if_index[il->il_sw_if_index];
     612             : 
     613           0 :   while (ai != (u32) ~ 0)
     614             :     {
     615           0 :       a = pool_elt_at_index (lm->if_address_pool, ai);
     616           0 :       ip6_address_t *address = ip_interface_address_get_address (lm, a);
     617             : 
     618           0 :       if (ip6_address_is_link_local_unicast (address))
     619           0 :         vec_add1 (link_scope, ai);
     620           0 :       else if (ip6_address_is_global_unicast (address))
     621           0 :         vec_add1 (global_scope, ai);
     622           0 :       else if (ip6_address_is_local_unicast (address))
     623           0 :         vec_add1 (local_scope, ai);
     624             :       else
     625           0 :         vec_add1 (unknown_scope, ai);
     626             : 
     627           0 :       ai = a->next_this_sw_interface;
     628             :     }
     629             : 
     630           0 :   if (vec_len (link_scope))
     631             :     {
     632           0 :       s = format (s, "%ULink-local address(es):\n", format_white_space, 2);
     633           0 :       s = ip6_print_addrs (s, link_scope);
     634           0 :       vec_free (link_scope);
     635             :     }
     636             : 
     637           0 :   if (vec_len (local_scope))
     638             :     {
     639           0 :       s = format (s, "%ULocal unicast address(es):\n", format_white_space, 2);
     640           0 :       s = ip6_print_addrs (s, local_scope);
     641           0 :       vec_free (local_scope);
     642             :     }
     643             : 
     644           0 :   if (vec_len (global_scope))
     645             :     {
     646           0 :       s = format (s, "%UGlobal unicast address(es):\n",
     647             :                   format_white_space, 2);
     648           0 :       s = ip6_print_addrs (s, global_scope);
     649           0 :       vec_free (global_scope);
     650             :     }
     651             : 
     652           0 :   if (vec_len (unknown_scope))
     653             :     {
     654           0 :       s = format (s, "%UOther-scope address(es):\n", format_white_space, 2);
     655           0 :       s = ip6_print_addrs (s, unknown_scope);
     656           0 :       vec_free (unknown_scope);
     657             :     }
     658             : 
     659           0 :   s = format (s, "%ULink-local address(es):\n", format_white_space, 2);
     660           0 :   s = format (s, "%U%U\n",
     661             :               format_white_space, 4, format_ip6_address, &il->il_ll_addr);
     662             : 
     663             :   /* *INDENT-OFF* */
     664           0 :   FOREACH_IP6_LINK_DELEGATE(ild, il,
     665             :   ({
     666             :     s = format (s, "%U", il_delegate_vfts[ild->ild_type].ildv_format,
     667             :                      ild->ild_index, 2);
     668             :   }));
     669             :   /* *INDENT-ON* */
     670             : 
     671           0 :   return (s);
     672             : }
     673             : 
     674             : static clib_error_t *
     675           0 : ip6_link_show (vlib_main_t * vm,
     676             :                unformat_input_t * input, vlib_cli_command_t * cmd)
     677             : {
     678             :   const ip6_link_t *il;
     679             :   vnet_main_t *vnm;
     680             :   u32 sw_if_index;
     681             : 
     682           0 :   vnm = vnet_get_main ();
     683           0 :   sw_if_index = ~0;
     684             : 
     685           0 :   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     686             :     {
     687           0 :       il = ip6_link_get (sw_if_index);
     688             : 
     689           0 :       if (NULL == il)
     690             :         {
     691           0 :           vlib_cli_output (vm, "IP6 disabled");
     692           0 :           return (NULL);
     693             :         }
     694             :       else
     695           0 :         vlib_cli_output (vm, "%U", format_ip6_link, il);
     696             :     }
     697             :   else
     698             :     {
     699           0 :       vec_foreach (il, ip6_links)
     700           0 :         vlib_cli_output (vm, "%U", format_ip6_link, il);
     701             :     }
     702             : 
     703           0 :   return (NULL);
     704             : }
     705             : 
     706             : /*?
     707             :  * This command is used to display various IPv6 attributes on a given
     708             :  * interface.
     709             :  *
     710             :  * @cliexpar
     711             :  * Example of how to display IPv6 settings:
     712             :  * @cliexstart{show ip6 interface GigabitEthernet2/0/0}
     713             :  * GigabitEthernet2/0/0 is admin up
     714             :  *         Link-local address(es):
     715             :  *                 fe80::ab8/64
     716             :  *         Joined group address(es):
     717             :  *                 ff02::1
     718             :  *                 ff02::2
     719             :  *                 ff02::16
     720             :  *                 ff02::1:ff00:ab8
     721             :  *         Advertised Prefixes:
     722             :  *                 prefix fe80::fe:28ff:fe9c:75b3,  length 64
     723             :  *         MTU is 1500
     724             :  *         ICMP error messages are unlimited
     725             :  *         ICMP redirects are disabled
     726             :  *         ICMP unreachables are not sent
     727             :  *         ND DAD is disabled
     728             :  *         ND advertised reachable time is 0
     729             :  *         ND advertised retransmit interval is 0 (msec)
     730             :  *         ND router advertisements are sent every 200 seconds (min interval is 150)
     731             :  *         ND router advertisements live for 600 seconds
     732             :  *         Hosts use stateless autoconfig for addresses
     733             :  *         ND router advertisements sent 19336
     734             :  *         ND router solicitations received 0
     735             :  *         ND router solicitations dropped 0
     736             :  * @cliexend
     737             :  * Example of output if IPv6 is not enabled on the interface:
     738             :  * @cliexstart{show ip6 interface GigabitEthernet2/0/0}
     739             :  * show ip6 interface: IPv6 not enabled on interface
     740             :  * @cliexend
     741             : ?*/
     742             : /* *INDENT-OFF* */
     743      285289 : VLIB_CLI_COMMAND (ip6_link_show_command, static) =
     744             : {
     745             :   .path = "show ip6 interface",
     746             :   .function = ip6_link_show,
     747             :   .short_help = "show ip6 interface <interface>",
     748             : };
     749             : /* *INDENT-ON* */
     750             : 
     751             : static clib_error_t *
     752           0 : enable_ip6_interface_cmd (vlib_main_t * vm,
     753             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     754             : {
     755           0 :   vnet_main_t *vnm = vnet_get_main ();
     756           0 :   clib_error_t *error = NULL;
     757             :   u32 sw_if_index;
     758             : 
     759           0 :   sw_if_index = ~0;
     760             : 
     761           0 :   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     762             :     {
     763           0 :       if (ip6_link_enable (sw_if_index, NULL))
     764           0 :         error = clib_error_return (0, "Failed\n");
     765             :     }
     766             :   else
     767             :     {
     768           0 :       error = clib_error_return (0, "unknown interface\n'",
     769             :                                  format_unformat_error, input);
     770             : 
     771             :     }
     772           0 :   return error;
     773             : }
     774             : 
     775             : /*?
     776             :  * This command is used to enable IPv6 on a given interface.
     777             :  *
     778             :  * @cliexpar
     779             :  * Example of how enable IPv6 on a given interface:
     780             :  * @cliexcmd{enable ip6 interface GigabitEthernet2/0/0}
     781             : ?*/
     782             : /* *INDENT-OFF* */
     783      285289 : VLIB_CLI_COMMAND (enable_ip6_interface_command, static) =
     784             : {
     785             :   .path = "enable ip6 interface",
     786             :   .function = enable_ip6_interface_cmd,
     787             :   .short_help = "enable ip6 interface <interface>",
     788             : };
     789             : /* *INDENT-ON* */
     790             : 
     791             : static clib_error_t *
     792           0 : disable_ip6_interface_cmd (vlib_main_t * vm,
     793             :                            unformat_input_t * input, vlib_cli_command_t * cmd)
     794             : {
     795           0 :   vnet_main_t *vnm = vnet_get_main ();
     796           0 :   clib_error_t *error = NULL;
     797             :   u32 sw_if_index;
     798             : 
     799           0 :   sw_if_index = ~0;
     800             : 
     801           0 :   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     802             :     {
     803           0 :       if (ip6_link_disable (sw_if_index))
     804           0 :         error = clib_error_return (0, "Failed\n");
     805             :     }
     806             :   else
     807             :     {
     808           0 :       error = clib_error_return (0, "unknown interface\n'",
     809             :                                  format_unformat_error, input);
     810             : 
     811             :     }
     812           0 :   return error;
     813             : }
     814             : 
     815             : /*?
     816             :  * This command is used to disable IPv6 on a given interface.
     817             :  *
     818             :  * @cliexpar
     819             :  * Example of how disable IPv6 on a given interface:
     820             :  * @cliexcmd{disable ip6 interface GigabitEthernet2/0/0}
     821             : ?*/
     822             : /* *INDENT-OFF* */
     823      285289 : VLIB_CLI_COMMAND (disable_ip6_interface_command, static) =
     824             : {
     825             :   .path = "disable ip6 interface",
     826             :   .function = disable_ip6_interface_cmd,
     827             :   .short_help = "disable ip6 interface <interface>",
     828             : };
     829             : /* *INDENT-ON* */
     830             : 
     831             : /*
     832             :  * fd.io coding-style-patch-verification: ON
     833             :  *
     834             :  * Local Variables:
     835             :  * eval: (c-set-style "gnu")
     836             :  * End:
     837             :  */

Generated by: LCOV version 1.14