1/*
2 * interface.c: mpls interfaces
3 *
4 * Copyright (c) 2012 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <vnet/vnet.h>
19#include <vnet/pg/pg.h>
20#include <vnet/mpls/mpls.h>
21#include <vnet/fib/mpls_fib.h>
22#include <vnet/fib/ip4_fib.h>
23#include <vnet/adj/adj_midchain.h>
24#include <vnet/dpo/classify_dpo.h>
25
26
27u8
28mpls_sw_interface_is_enabled (u32 sw_if_index)
29{
30    mpls_main_t * mm = &mpls_main;
31
32    if (vec_len(mm->mpls_enabled_by_sw_if_index) <= sw_if_index)
33        return (0);
34
35    return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
36}
37
38int
39mpls_sw_interface_enable_disable (mpls_main_t * mm,
40                                  u32 sw_if_index,
41                                  u8 is_enable,
42                                  u8 is_api)
43{
44  fib_node_index_t lfib_index;
45
46  vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
47
48  lfib_index = fib_table_find(FIB_PROTOCOL_MPLS,
49                              MPLS_FIB_DEFAULT_TABLE_ID);
50
51  if (~0 == lfib_index)
52       return VNET_API_ERROR_NO_SUCH_FIB;
53
54  /*
55   * enable/disable only on the 1<->0 transition
56   */
57  if (is_enable)
58    {
59      if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
60          return (0);
61
62      fib_table_lock(lfib_index, FIB_PROTOCOL_MPLS,
63                     (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
64
65      vec_validate(mm->fib_index_by_sw_if_index, sw_if_index);
66      mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
67    }
68  else
69    {
70      ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
71      if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
72          return (0);
73
74      fib_table_unlock(mm->fib_index_by_sw_if_index[sw_if_index],
75		       FIB_PROTOCOL_MPLS,
76                       (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
77    }
78
79  vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled",
80                               sw_if_index, !is_enable, 0, 0);
81
82  return (0);
83}
84
85static clib_error_t *
86mpls_interface_enable_disable (vlib_main_t * vm,
87                               unformat_input_t * input,
88                               vlib_cli_command_t * cmd)
89{
90  vnet_main_t * vnm = vnet_get_main();
91  clib_error_t * error = 0;
92  u32 sw_if_index, enable;
93  int rv;
94
95  sw_if_index = ~0;
96
97  if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
98    {
99      error = clib_error_return (0, "unknown interface `%U'",
100				 format_unformat_error, input);
101      goto done;
102    }
103
104  if (unformat (input, "enable"))
105      enable = 1;
106  else if (unformat (input, "disable"))
107      enable = 0;
108  else
109    {
110      error = clib_error_return (0, "expected 'enable' or 'disable'",
111				 format_unformat_error, input);
112      goto done;
113    }
114
115  rv = mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable, 0);
116
117  if (VNET_API_ERROR_NO_SUCH_FIB == rv)
118      error = clib_error_return (0, "default MPLS table must be created first");
119
120 done:
121  return error;
122}
123
124/*?
125 * This command enables an interface to accpet MPLS packets
126 *
127 * @cliexpar
128 * @cliexstart{set interface mpls}
129 *  set interface mpls GigEthernet0/8/0 enable
130 * @cliexend
131 ?*/
132VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = {
133  .path = "set interface mpls",
134  .function = mpls_interface_enable_disable,
135  .short_help = "Enable/Disable an interface for MPLS forwarding",
136};
137