/* * Copyright (c) 2015 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * interface.c: VNET interfaces/sub-interfaces * * Copyright (c) 2008 Eliot Dresselhaus * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <vnet/vnet.h> #include <vnet/plugin/plugin.h> #include <vnet/adj/adj.h> #include <vnet/adj/adj_mcast.h> #include <vnet/ip/ip.h> #include <vnet/interface/rx_queue_funcs.h> #include <vnet/interface/tx_queue_funcs.h> /* *INDENT-OFF* */ VLIB_REGISTER_LOG_CLASS (if_default_log, static) = { .class_name = "interface", }; /* *INDENT-ON* */ #define log_debug(fmt,...) vlib_log_debug(if_default_log.class, fmt, __VA_ARGS__) #define log_err(fmt,...) vlib_log_err(if_default_log.class, fmt, __VA_ARGS__) typedef enum vnet_interface_helper_flags_t_ { VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE = (1 << 0), VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE = (1 << 1), } vnet_interface_helper_flags_t; static clib_error_t *vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags, vnet_interface_helper_flags_t helper_flags); static clib_error_t *vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags, vnet_interface_helper_flags_t helper_flags); static clib_error_t *vnet_hw_interface_set_class_helper (vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index, u32 redistribute); typedef struct { /* Either sw or hw interface index. */ u32 sw_hw_if_index; /* Flags. */ u32 flags; } vnet_sw_hw_interface_state_t; static void serialize_vec_vnet_sw_hw_interface_state (serialize_main_t * m, va_list * va) { vnet_sw_hw_interface_state_t *s = va_arg (*va, vnet_sw_hw_interface_state_t *); u32 n = va_arg (*va, u32); u32 i; for (i = 0; i < n; i++) { serialize_integer (m, s[i].sw_hw_if_index, sizeof (s[i].sw_hw_if_index)); serialize_integer (m, s[i].flags, sizeof (s[i].flags)); } } static void unserialize_vec_vnet_sw_hw_interface_state (serialize_main_t * m, va_list * va) { vnet_sw_hw_interface_state_t *s = va_arg (*va, vnet_sw_hw_interface_state_t *); u32 n = va_arg (*va, u32); u32 i; for (i = 0; i < n; i++) { unserialize_integer (m, &s[i].sw_hw_if_index, sizeof (s[i].sw_hw_if_index)); unserialize_integer (m, &s[i].flags, sizeof (s[i].flags)); } } static vnet_sw_interface_flags_t vnet_hw_interface_flags_to_sw (vnet_hw_interface_flags_t hwf) { vnet_sw_interface_flags_t swf = VNET_SW_INTERFACE_FLAG_NONE; if (hwf & VNET_HW_INTERFACE_FLAG_LINK_UP) swf |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; return (swf); } void serialize_vnet_interface_state (serialize_main_t * m, va_list * va) { vnet_main_t *vnm = va_arg (*va, vnet_main_t *); vnet_sw_hw_interface_state_t *sts = 0, *st; vnet_sw_interface_t *sif; vnet_hw_interface_t *hif; vnet_interface_main_t *im = &vnm->interface_main; /* Serialize hardware interface classes since they may have changed. Must do this before sending up/down flags. */ /* *INDENT-OFF* */ pool_foreach (hif, im->hw_interfaces) { vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hif->hw_class_index); serialize_cstring (m, hw_class->name); } /* *INDENT-ON* */ /* Send sw/hw interface state when non-zero. */ /* *INDENT-OFF* */ pool_foreach (sif, im->sw_interfaces) { if (sif->flags != 0) { vec_add2 (sts, st, 1); st->sw_hw_if_index = sif->sw_if_index; st->flags = sif->flags; } } /* *INDENT-ON* */ vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state); if (sts) _vec_len (sts) = 0; /* *INDENT-OFF* */ pool_foreach (hif, im->hw_interfaces) { if (hif->flags != 0) { vec_add2 (sts, st, 1); st->sw_hw_if_index = hif->hw_if_index; st->flags = vnet_hw_interface_flags_to_sw(hif->flags); } } /* *INDENT-ON* */ vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state); vec_free (sts); } static vnet_hw_interface_flags_t vnet_sw_interface_flags_to_hw (vnet_sw_interface_flags_t swf) { vnet_hw_interface_flags_t hwf = VNET_HW_INTERFACE_FLAG_NONE; if (swf & VNET_SW_INTERFACE_FLAG_ADMIN_UP) hwf |= VNET_HW_INTERFACE_FLAG_LINK_UP; return (hwf); } void unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) { vnet_main_t *vnm = va_arg (*va, vnet_main_t *); vnet_sw_hw_interface_state_t *sts = 0, *st; /* First set interface hardware class. */ { vnet_interface_main_t *im = &vnm->interface_main; vnet_hw_interface_t *hif; char *class_name; uword *p; clib_error_t *error; /* *INDENT-OFF* */ pool_foreach (hif, im->hw_interfaces) { unserialize_cstring (m, &class_name); p = hash_get_mem (im->hw_interface_class_by_name, class_name); if (p) { error = vnet_hw_interface_set_class_helper (vnm, hif->hw_if_index, p[0], /* redistribute */ 0); } else error = clib_error_return (0, "hw class %s AWOL?", class_name); if (error) clib_error_report (error); vec_free (class_name); } /* *INDENT-ON* */ } vec_unserialize (m, &sts, unserialize_vec_vnet_sw_hw_interface_state); vec_foreach (st, sts) vnet_sw_interface_set_flags_helper (vnm, st->sw_hw_if_index, st->flags, /* no distribute */ 0); vec_free (sts); vec_unserialize (m, &sts, unserialize_vec_vnet_sw_hw_interface_state); vec_foreach (st, sts) { vnet_hw_interface_set_flags_helper (vnm, st->sw_hw_if_index, vnet_sw_interface_flags_to_hw (st->flags), /* no distribute */ 0); } vec_free (sts); } static clib_error_t * call_elf_section_interface_callbacks (vnet_main_t * vnm, u32 if_index, u32 flags, _vnet_interface_function_list_elt_t ** elts) { _vnet_interface_function_list_elt_t *elt; vnet_interface_function_priority_t prio; clib_error_t *error = 0; for (prio = VNET_ITF_FUNC_PRIORITY_LOW; prio <= VNET_ITF_FUNC_PRIORITY_HIGH; prio++) { elt = elts[prio]; while (elt) { error = elt->fp (vnm, if_index, flags); if (error) return error; elt = elt->next_interface_function; } } return error; } static clib_error_t * call_hw_interface_add_del_callbacks (vnet_main_t * vnm, u32 hw_if_index, u32 is_create) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); vnet_hw_interface_class_t *hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi->dev_class_index); clib_error_t *error = 0; if (hw_class->interface_add_del_function && (error = hw_class->interface_add_del_function (vnm, hw_if_index, is_create))) return error; if (dev_class->interface_add_del_function && (error = dev_class->interface_add_del_function (vnm, hw_if_index, is_create))) return error; error = call_elf_section_interface_callbacks (vnm, hw_if_index, is_create, vnm->hw_interface_add_del_functions); return error; } static clib_error_t * call_sw_interface_add_del_callbacks (vnet_main_t * vnm, u32 sw_if_index, u32 is_create) { return call_elf_section_interface_callbacks (vnm, sw_if_index, is_create, vnm->sw_interface_add_del_functions); } static clib_error_t * vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags, vnet_interface_helper_flags_t helper_flags) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); vnet_hw_interface_class_t *hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); u32 mask; clib_error_t *error = 0; u32 is_create = (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0; mask = (VNET_HW_INTERFACE_FLAG_LINK_UP | VNET_HW_INTERFACE_FLAG_DUPLEX_MASK); flags &= mask; /* Call hardware interface add/del callbacks. */ if (is_create) call_hw_interface_add_del_callbacks (vnm, hw_if_index, is_create); /* Already in the desired state? */ if (!is_create && (hi->flags & mask) == flags) goto done; if ((hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) != (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)) { /* Do hardware class (e.g. ethernet). */ if (hw_class->link_up_down_function && (error = hw_class->link_up_down_function (vnm, hw_if_index, flags))) goto done; error = call_elf_section_interface_callbacks (vnm, hw_if_index, flags, vnm->hw_interface_link_up_down_functions); if (error) goto done; } hi->flags &= ~mask; hi->flags |= flags; done: if (error) log_err ("hw_set_flags_helper: %U", format_clib_error, error); return error; } static clib_error_t * vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags, vnet_interface_helper_flags_t helper_flags) { vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); u32 mask; clib_error_t *error = 0; u32 is_create = (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0; u32 old_flags; mask = VNET_SW_INTERFACE_FLAG_ADMIN_UP | VNET_SW_INTERFACE_FLAG_PUNT; flags &= mask; if (is_create) { error = call_sw_interface_add_del_callbacks (vnm, sw_if_index, is_create); if (error) goto done; if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) { /* Notify everyone when the interface is created as admin up */ error = call_elf_section_interface_callbacks (vnm, sw_if_index, flags, vnm-> sw_interface_admin_up_down_functions); if (error) goto done; } } else { vnet_sw_interface_t *si_sup = si; /* Check that super interface is in correct state. */ if (si->type == VNET_SW_INTERFACE_TYPE_SUB) { si_sup = vnet_get_sw_interface (vnm, si->sup_sw_if_index); /* Check to see if we're bringing down the soft interface and if it's parent is up */ if ((flags != (si_sup->flags & mask)) && (!((flags == 0) && ((si_sup->flags & mask) == VNET_SW_INTERFACE_FLAG_ADMIN_UP)))) { error = clib_error_return (0, "super-interface %U must be %U", format_vnet_sw_interface_name, vnm, si_sup, format_vnet_sw_interface_flags, flags); goto done; } } /* Already in the desired state? */ if ((si->flags & mask) == flags) goto done; /* Sub-interfaces of hardware interfaces that do no redistribute, do not redistribute themselves. */ if (si_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, si_sup->hw_if_index); vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi->dev_class_index); if (!dev_class->redistribute) helper_flags &= ~VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE; } /* set the flags now before invoking the registered clients * so that the state they query is consistent with the state here notified */ old_flags = si->flags; si->flags &= ~mask; si->flags |= flags; if ((flags | old_flags) & VNET_SW_INTERFACE_FLAG_ADMIN_UP) error = call_elf_section_interface_callbacks (vnm, sw_if_index, flags, vnm->sw_interface_admin_up_down_functions); if (error) { /* restore flags on error */ si->flags = old_flags; goto done; } if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, si->hw_if_index); vnet_hw_interface_class_t *hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi-<style> @media only all and (prefers-color-scheme: dark) { .highlight .hll { background-color: #49483e } .highlight .c { color: #75715e } /* Comment */ .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ .highlight .k { color: #66d9ef } /* Keyword */ .highlight .l { color: #ae81ff } /* Literal */ .highlight .n { color: #f8f8f2 } /* Name */ .highlight .o { color: #f92672 } /* Operator */ .highlight .p { color: #f8f8f2 } /* Punctuation */ .highlight .ch { color: #75715e } /* Comment.Hashbang */ .highlight .cm { color: #75715e } /* Comment.Multiline */ .highlight .cp { color: #75715e } /* Comment.Preproc */ .highlight .cpf { color: #75715e } /* Comment.PreprocFile */ .highlight .c1 { color: #75715e } /* Comment.Single */ .highlight .cs { color: #75715e } /* Comment.Special */ .highlight .gd { color: #f92672 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gi { color: #a6e22e } /* Generic.Inserted */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #75715e } /* Generic.Subheading */ .highlight .kc { color: #66d9ef } /* Keyword.Constant */ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ } </style><div class="highlight"><pre><span></span><span class="cm">/*</span> <span class="cm"> *------------------------------------------------------------------</span> <span class="cm"> * api_common.h</span> <span class="cm"> *</span> <span class="cm"> * Copyright (c) 2009-2015 Cisco and/or its affiliates.</span> <span class="cm"> * Licensed under the Apache License, Version 2.0 (the "License");</span> <span class="cm"> * you may not use this file except in compliance with the License.</span> <span class="cm"> * You may obtain a copy of the License at:</span> <span class="cm"> *</span> <span class="cm"> * http://www.apache.org/licenses/LICENSE-2.0</span> <span class="cm"> *</span> <span class="cm"> * Unless required by applicable law or agreed to in writing, software</span> <span class="cm"> * distributed under the License is distributed on an "AS IS" BASIS,</span> <span class="cm"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span> <span class="cm"> * See the License for the specific language governing permissions and</span> <span class="cm"> * limitations under the License.</span> <span class="cm"> *------------------------------------------------------------------</span> <span class="cm"> */</span> <span class="cp">#ifndef included_api_common_h</span> <span class="cp">#define included_api_common_h</span> <span class="cp">#include</span> <span class="cpf"><vppinfra/clib_error.h></span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf"><svm/svm_common.h></span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf"><vlibmemory/unix_shared_memory_queue.h></span><span class="cp"></span> <span class="k">typedef</span> <span class="k">enum</span> <span class="p">{</span> <span class="n">REGISTRATION_TYPE_FREE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">REGISTRATION_TYPE_SHMEM</span><span class="p">,</span> <span class="n">REGISTRATION_TYPE_SOCKET_LISTEN</span><span class="p">,</span> <span class="n">REGISTRATION_TYPE_SOCKET_SERVER</span><span class="p">,</span> <span class="n">REGISTRATION_TYPE_SOCKET_CLIENT</span><span class="p">,</span> <span class="p">}</span> <span class="n">vl_registration_type_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="n">vl_api_registration_</span> <span class="p">{</span> <span class="n">vl_registration_type_t</span> <span class="n">registration_type</span><span class="p">;</span> <span class="cm">/* Index in VLIB's brain (not shared memory). */</span> <span class="n">u32</span> <span class="n">vl_api_registration_pool_index</span><span class="p">;</span> <span class="n">u8</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> <span class="cm">/*</span> <span class="cm"> * The following groups of data could be unioned, but my fingers are</span> <span class="cm"> * going to be sore enough.</span> <span class="cm"> */</span> <span class="cm">/* shared memory only */</span> <span class="n">unix_shared_memory_queue_t</span> <span class="o">*</span><span class="n">vl_input_queue</span><span class="p">;</span> <span class="cm">/* socket server and client */</span> <span class="n">u32</span> <span class="n">unix_file_index</span><span class="p">;</span> <span class="n">i8</span> <span class="o">*</span><span class="n">unprocessed_input</span><span class="p">;</span> <span class="n">u32</span> <span class="n">unprocessed_msg_length</span><span class="p">;</span> <span class="n">u8</span> <span class="o">*</span><span class="n">output_vector</span><span class="p">;</span> <span class="cm">/* socket client only */</span> <span class="n">u32</span> <span class="n">server_handle</span><span class="p">;</span> <span class="n">u32</span> <span class="n">server_index</span><span class="p">;</span> <span class="p">}</span> <span class="n">vl_api_registration_t</span><span class="p">;</span> <span class="cm">/* Trace configuration for a single message */</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">size</span><span class="p">;</span> <span class="kt">int</span> <span class="n">trace_enable</span><span class="p">;</span> <span class="kt">int</span> <span class="n">replay_enable</span><span class="p">;</span> <span class="p">}</span> <span class="n">trace_cfg_t</span><span class="p">;</span> <span class="cm">/*</span> <span class="cm"> * API recording</span> <span class="cm"> */</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span> <span class="n">u8</span> <span class="n">endian</span><span class="p">;</span> <span class="n">u8</span> <span class="n">enabled</span><span class="p">;</span> <span class="n">u8</span> <span class="n">wrapped</span><span class="p">;</span> <span class="n">u8</span> <span class="n">pad</span><span class="p">;</span> <span class="n">u32</span> <span class="n">nitems</span><span class="p">;</span> <span class="n">u32</span> <span class="n">curindex</span><span class="p">;</span> <span class="n">u8</span> <span class="o">**</span><span class="n">traces</span><span class="p">;</span> <span class="p">}</span> <span class="n">vl_api_trace_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">enum</span> <span class="p">{</span> <span class="n">VL_API_TRACE_TX</span><span class="p">,</span> <span class="n">VL_API_TRACE_RX</span><span class="p">,</span> <span class="p">}</span> <span class="n">vl_api_trace_which_t</span><span class="p">;</span> <span class="cp">#define VL_API_LITTLE_ENDIAN 0x00</span> <span class="cp">#define VL_API_BIG_ENDIAN 0x01</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span> <span class="n">u8</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> <span class="n">u16</span> <span class="n">first_msg_id</span><span class="p">;</span> <span class="n">u16</span> <span class="n">last_msg_id</span><span class="p">;</span> <span class="p">}</span> <span class="n">vl_api_msg_range_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">id</span><span class="p">;</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> <span class="n">u32</span> <span class="n">crc</span><span class="p">;</span> <span class="kt">void</span> <span class="o">*</span><span class="n">handler</span><span class="p">;</span> <span class="kt">void</span> <span class="o">*</span><span class="n">cleanup</span><span class="p">;</span> <span class="kt">void</span> <span class="o">*</span><span class="n">endian</span><span class="p">;</span> <span class="kt">void</span> <span class="o">*</span><span class="n">print</span><span class="p">;</span> <span class="kt">int</span> <span class="n">size</span><span class="p">;</span> <span class="kt">int</span> <span class="n">traced</span><span class="p">;</span> <span class="kt">int</span> <span class="n">replay</span><span class="p">;</span> <span class="kt">int</span> <span class="n">message_bounce</span><span class="p">;</span> <span class="kt">int</span> <span class="n">is_mp_safe</span><span class="p">;</span> <span class="p">}</span> <span class="n">vl_msg_api_msg_config_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="n">msgbuf_</span> <span class="p">{</span> <span class="n">unix_shared_memory_queue_t</span> <span class="o">*</span><span class="n">q</span><span class="p">;</span> <span class="n">u32</span> <span class="n">data_len</span><span class="p">;</span> <span class="n">u32</span> <span class="n">gc_mark_timestamp</span><span class="p">;</span> <span class="n">u8</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="p">}</span> <span class="n">msgbuf_t</span><span class="p">;</span> <span class="cm">/* api_shared.c prototypes */</span> <span class="kt">void</span> <span class="nf">vl_msg_api_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_handler_no_free</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_handler_no_trace_no_free</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_trace_only</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_cleanup_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_replay_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_socket_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">the_msg</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_set_handlers</span> <span class="p">(</span><span class="kt">int</span> <span class="n">msg_id</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">msg_name</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">handler</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">cleanup</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">endian</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">print</span><span class="p">,</span> <span class="kt">int</span> <span class="n">msg_size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">traced</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_config</span> <span class="p">(</span><span class="n">vl_msg_api_msg_config_t</span> <span class="o">*</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_set_cleanup_handler</span> <span class="p">(</span><span class="kt">int</span> <span class="n">msg_id</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">fp</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_queue_handler</span> <span class="p">(</span><span class="n">unix_shared_memory_queue_t</span> <span class="o">*</span> <span class="n">q</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_barrier_sync</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span> <span class="p">((</span><span class="n">weak</span><span class="p">));</span> <span class="kt">void</span> <span class="nf">vl_msg_api_barrier_release</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span> <span class="p">((</span><span class="n">weak</span><span class="p">));</span> <span class="kt">void</span> <span class="nf">vl_msg_api_free</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_noop_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">mp</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_increment_missing_client_counter</span> <span class="p">(</span><span class="kt">void</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_post_mortem_dump</span> <span class="p">(</span><span class="kt">void</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_post_mortem_dump_enable_disable</span> <span class="p">(</span><span class="kt">int</span> <span class="n">enable</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_register_pd_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">handler</span><span class="p">,</span> <span class="n">u16</span> <span class="n">msg_id_host_byte_order</span><span class="p">);</span> <span class="kt">int</span> <span class="nf">vl_msg_api_pd_handler</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">mp</span><span class="p">,</span> <span class="kt">int</span> <span class="n">rv</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">vl_msg_api_set_first_available_msg_id</span> <span class="p">(</span><span class="n">u16</span> <span class="n">first_avail</span><span class="p">);</span> <span class="n">u16</span> <span class="nf">vl_msg_api_get_msg_ids</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span> <span class="n">u32</span> <span class="nf">vl_api_get_msg_index</span> <span class="p">(</span><span class="n">u8</span> <span class="o">*</span> <span class="n">name_and_crc</span><span class="p">);</span> <span class="k">typedef</span> <span class="n">clib_error_t</span> <span class="o">*</span><span class="p">(</span><span class="n">vl_msg_api_init_function_t</span><span class="p">)</span> <span class="p">(</span><span class="n">u32</span> <span class="n">client_index</span><span class="p">);</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="n">_vl_msg_api_init_function_list_elt</span> <span class="p">{</span> <span class="k">struct</span> <span class="n">_vl_msg_api_init_function_list_elt</span> <span class="o">*</span><span class="n">next_init_function</span><span class="p">;</span> <span class="n">vl_msg_api_init_function_t</span> <span class="o">*</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span> <span class="n">_vl_msg_api_function_list_elt_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span> <span class="kt">void</span> <span class="p">(</span><span class="o">**</span><span class="n">msg_handlers</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">);</span> <span class="kt">int</span> <span class="p">(</span><span class="o">**</span><span class="n">pd_msg_handlers</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span> <span class="kt">void</span> <span class="p">(</span><span class="o">**</span><span class="n">msg_cleanup_handlers</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">);</span> <span class="kt">void</span> <span class="p">(</span><span class="o">**</span><span class="n">msg_endian_handlers</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">);</span> <span class="kt">void</span> <span class="p">(</span><span class="o">**</span><span class="n">msg_print_handlers</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="p">);</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">msg_names</span><span class="p">;</span> <span class="n">u8</span> <span class="o">*</span><span class="n">message_bounce</span><span class="p">;</span> <span class="n">u8</span> <span class="o">*</span><span class="n">is_mp_safe</span><span class="p">;</span> <span class="k">struct</span> <span class="n">ring_alloc_</span> <span class="o">*</span><span class="n">arings</span><span class="p">;</span> <span class="n">u32</span> <span class="n">ring_misses</span><span class="p">;</span> <span class="n">u32</span> <span class="n">garbage_collects</span><span class="p">;</span> <span class="n">u32</span> <span class="n">missing_clients</span><span class="p">;</span> <span class="n">vl_api_trace_t</span> <span class="o">*</span><span class="n">rx_trace</span><span class="p">;</span> <span class="n">vl_api_trace_t</span> <span class="o">*</span><span class="n">tx_trace</span><span class="p">;</span> <span class="kt">int</span> <span class="n">msg_print_flag</span><span class="p">;</span> <span class="n">trace_cfg_t</span> <span class="o">*</span><span class="n">api_trace_cfg</span><span class="p">;</span> <span class="kt">int</span> <span class="n">our_pid</span><span class="p">;</span> <span class="n">svm_region_t</span> <span class="o">*</span><span class="n">vlib_rp</span><span class="p">;</span> <span class="n">svm_region_t</span> <span class="o">**</span><span class="n">mapped_shmem_regions</span><span class="p">;</span> <span class="k">struct</span> <span class="n">vl_shmem_hdr_</span> <span class="o">*</span><span class="n">shmem_hdr</span><span class="p">;</span> <span class="n">vl_api_registration_t</span> <span class="o">**</span><span class="n">vl_clients</span><span class="p">;</span> <span class="n">u8</span> <span class="o">*</span><span class="n">serialized_message_table_in_shmem</span><span class="p">;</span> <span class="cm">/* For plugin msg allocator */</span> <span class="n">u16</span> <span class="n">first_available_msg_id</span><span class="p">;</span> <span class="cm">/* message range by name hash */</span> <span class="n">uword</span> <span class="o">*</span><span class="n">msg_range_by_name</span><span class="p">;</span> <span class="cm">/* vector of message ranges */</span> <span class="n">vl_api_msg_range_t</span> <span class="o">*</span><span class="n">msg_ranges</span><span class="p">;</span> <span class="cm">/* uid for the api shared memory region */</span> <span class="kt">int</span> <span class="n">api_uid</span><span class="p">;</span> <span class="cm">/* gid for the api shared memory region */</span> <span class="kt">int</span> <span class="n">api_gid</span><span class="p">;</span> <span class="cm">/* base virtual address for global VM region */</span> <span class="n">u64</span> <span class="n">global_baseva</span><span class="p">;</span> <span class="cm">/* size of the global VM region */</span> <span class="n">u64</span> <span class="n">global_size</span><span class="p">;</span> <span class="cm">/* size of the API region */</span> <span class="n">u64</span> <span class="n">api_size</span><span class="p">;</span> <span class="cm">/* size of the global VM private mheap */</span> <span class="n">u64</span> <span class="n">global_pvt_heap_size</span><span class="p">;</span> <span class="cm">/* size of the api private mheap */</span> <span class="n">u64</span> <span class="n">api_pvt_heap_size</span><span class="p">;</span> <span class="cm">/* Client-only data structures */</span> <span class="n">unix_shared_memory_queue_t</span> <span class="o">*</span><span class="n">vl_input_queue</span><span class="p">;</span> <span class="cm">/*</span> <span class="cm"> * All VLIB-side message handlers use my_client_index to identify</span> <span class="cm"> * the queue / client. This works in sim replay.</span> <span class="cm"> */</span> <span class="kt">int</span> <span class="n">my_client_index</span><span class="p">;</span> <span class="cm">/*</span> <span class="cm"> * This is the (shared VM) address of the registration,</span> <span class="cm"> * don't use it to id the connection since it can't possibly</span> <span class="cm"> * work in simulator replay.</span> <span class="cm"> */</span> <span class="n">vl_api_registration_t</span> <span class="o">*</span><span class="n">my_registration</span><span class="p">;</span> <span class="n">i32</span> <span class="n">vlib_signal</span><span class="p">;</span> <span class="cm">/* vlib input queue length */</span> <span class="n">u32</span> <span class="n">vlib_input_queue_length</span><span class="p">;</span> <span class="cm">/* client side message index hash table */</span> <span class="n">uword</span> <span class="o">*</span><span class="n">msg_index_by_name_and_crc</span><span class="p">;</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">region_name</span><span class="p">;</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">root_path</span><span class="p">;</span> <span class="cm">/* Replay in progress? */</span> <span class="kt">int</span> <span class="n">replay_in_progress</span><span class="p">;</span> <span class="cm">/* List of API client reaper functions */</span> <span class="n">_vl_msg_api_function_list_elt_t</span> <span class="o">*</span><span class="n">reaper_function_registrations</span><span class="p">;</span> <span class="p">}</span> <span class="n">api_main_t</span><span class="p">;</span> <span class="k">extern</span> <span class="n">api_main_t</span> <span class="n">api_main</span><span class="p">;</span> <span class="cp">#endif </span><span class="cm">/* included_api_common_h */</span><span class="cp"></span> <span class="cm">/*</span> <span class="cm"> * fd.io coding-style-patch-verification: ON</span> <span class="cm"> *</span> <span class="cm"> * Local Variables:</span> <span class="cm"> * eval: (c-set-style "gnu")</span> <span class="cm"> * End:</span> <span class="cm"> */</span> </pre></div> </code></pre></td></tr></table> </div> <!-- class=content --> <div id="lfcollabprojects-footer"> <div class="gray-diagonal"> <div class="footer-inner"> <p> © 2016 <a href="https://www.fd.io/">FD.io</a> a Linux Foundation Collaborative Project. All Rights Reserved. </p> <p> Linux Foundation is a registered trademark of The Linux Foundation. Linux is a registered <a href="http://www.linuxfoundation.org/programs/legal/trademark" title="Linux Mark Institute" >trademark</a > of Linus Torvalds. </p> <p> Please see our <a href="http://www.linuxfoundation.org/privacy">privacy policy</a> and <a href="http://www.linuxfoundation.org/terms">terms of use</a> </p> </div> </div> </div> </div> <!-- id=cgit --> </body> </html> _hw_interface_add_del_mac_address (vnet_main_t * vnm, u32 hw_if_index, const u8 * mac_address, u8 is_add) { clib_error_t *error = 0; vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi->dev_class_index); if (!hi->hw_address) { error = clib_error_return (0, "Secondary MAC Addresses not supported for interface index %u", hw_if_index); goto done; } if (dev_class->mac_addr_add_del_function) error = dev_class->mac_addr_add_del_function (hi, mac_address, is_add); if (!error) { vnet_hw_interface_class_t *hw_class; hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); if (NULL != hw_class->mac_addr_add_del_function) error = hw_class->mac_addr_add_del_function (hi, mac_address, is_add); } /* If no errors, add to the list of secondary MACs on the ethernet intf */ if (!error) ethernet_interface_add_del_address (ðernet_main, hw_if_index, mac_address, is_add); done: if (error) log_err ("hw_add_del_mac_address: %U", format_clib_error, error); return error; } static clib_error_t * vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, u32 hw_if_index, const u8 * mac_address) { clib_error_t *error = 0; vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); if (hi->hw_address) { u8 *old_address = vec_dup (hi->hw_address); vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi->dev_class_index); if (dev_class->mac_addr_change_function) { error = dev_class->mac_addr_change_function (hi, old_address, mac_address); } if (!error) { vnet_hw_interface_class_t *hw_class; hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); if (NULL != hw_class->mac_addr_change_function) hw_class->mac_addr_change_function (hi, old_address, mac_address); } else { error = clib_error_return (0, "MAC Address Change is not supported on this interface"); } vec_free (old_address); } else { error = clib_error_return (0, "mac address change is not supported for interface index %u", hw_if_index); } return error; } clib_error_t * vnet_hw_interface_change_mac_address (vnet_main_t * vnm, u32 hw_if_index, const u8 * mac_address) { return vnet_hw_interface_change_mac_address_helper (vnm, hw_if_index, mac_address); } static int vnet_sw_interface_check_table_same (u32 unnumbered_sw_if_index, u32 ip_sw_if_index) { if (ip4_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] != ip4_main.fib_index_by_sw_if_index[ip_sw_if_index]) return VNET_API_ERROR_UNEXPECTED_INTF_STATE; if (ip4_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] != ip4_main.mfib_index_by_sw_if_index[ip_sw_if_index]) return VNET_API_ERROR_UNEXPECTED_INTF_STATE; if (ip6_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] != ip6_main.fib_index_by_sw_if_index[ip_sw_if_index]) return VNET_API_ERROR_UNEXPECTED_INTF_STATE; if (ip6_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] != ip6_main.mfib_index_by_sw_if_index[ip_sw_if_index]) return VNET_API_ERROR_UNEXPECTED_INTF_STATE; return 0; } /* update the unnumbered state of an interface*/ int vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index, u32 ip_sw_if_index, u8 enable) { vnet_main_t *vnm = vnet_get_main (); vnet_sw_interface_t *si; u32 was_unnum; int rv = 0; si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index); was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED); if (enable) { rv = vnet_sw_interface_check_table_same (unnumbered_sw_if_index, ip_sw_if_index); if (rv != 0) return rv; si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = ip_sw_if_index; ip4_main.lookup_main.if_address_pool_index_by_sw_if_index [unnumbered_sw_if_index] = ip4_main. lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index]; ip6_main. lookup_main.if_address_pool_index_by_sw_if_index [unnumbered_sw_if_index] = ip6_main. lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index]; } else { /* * Unless the interface is actually unnumbered, don't * smash e.g. if_address_pool_index_by_sw_if_index */ if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) { si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~0; ip4_main.lookup_main .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0; ip6_main.lookup_main .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0; } } if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)) { ip4_sw_interface_enable_disable (unnumbered_sw_if_index, enable); ip6_sw_interface_enable_disable (unnumbered_sw_if_index, enable); } return 0; } vnet_l3_packet_type_t vnet_link_to_l3_proto (vnet_link_t link) { switch (link) { case VNET_LINK_IP4: return (VNET_L3_PACKET_TYPE_IP4); case VNET_LINK_IP6: return (VNET_L3_PACKET_TYPE_IP6); case VNET_LINK_MPLS: return (VNET_L3_PACKET_TYPE_MPLS); case VNET_LINK_ARP: return (VNET_L3_PACKET_TYPE_ARP); case VNET_LINK_ETHERNET: case VNET_LINK_NSH: ASSERT (0); break; } ASSERT (0); return (0); } vnet_mtu_t vnet_link_to_mtu (vnet_link_t link) { switch (link) { case VNET_LINK_IP4: return (VNET_MTU_IP4); case VNET_LINK_IP6: return (VNET_MTU_IP6); case VNET_LINK_MPLS: return (VNET_MTU_MPLS); default: return (VNET_MTU_L3); } } u8 * default_build_rewrite (vnet_main_t * vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address) { return (NULL); } void default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) { ip_adjacency_t *adj; adj = adj_get (ai); switch (adj->lookup_next_index) { case IP_LOOKUP_NEXT_GLEAN: adj_glean_update_rewrite (ai); break; case IP_LOOKUP_NEXT_ARP: case IP_LOOKUP_NEXT_BCAST: /* * default rewrite in neighbour adj */ adj_nbr_update_rewrite (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE, vnet_build_rewrite_for_sw_interface (vnm, sw_if_index, adj_get_link_type (ai), NULL)); break; case IP_LOOKUP_NEXT_MCAST: /* * mcast traffic also uses default rewrite string with no mcast * switch time updates. */ adj_mcast_update_rewrite (ai, vnet_build_rewrite_for_sw_interface (vnm, sw_if_index, adj_get_link_type (ai), NULL), 0); break; case IP_LOOKUP_NEXT_DROP: case IP_LOOKUP_NEXT_PUNT: case IP_LOOKUP_NEXT_LOCAL: case IP_LOOKUP_NEXT_REWRITE: case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: case IP_LOOKUP_NEXT_MIDCHAIN: case IP_LOOKUP_NEXT_ICMP_ERROR: case IP_LOOKUP_N_NEXT: ASSERT (0); break; } } clib_error_t * vnet_hw_interface_set_rss_queues (vnet_main_t * vnm, vnet_hw_interface_t * hi, clib_bitmap_t * bitmap) { clib_error_t *error = 0; vnet_device_class_t *dev_class = vnet_get_device_class (vnm, hi->dev_class_index); if (dev_class->set_rss_queues_function) { if (clib_bitmap_count_set_bits (bitmap) == 0) { error = clib_error_return (0, "must assign at least one valid rss queue"); goto done; } error = dev_class->set_rss_queues_function (vnm, hi, bitmap); } else { error = clib_error_return (0, "setting rss queues is not supported on this interface"); } if (!error) { clib_bitmap_free (hi->rss_queues); hi->rss_queues = clib_bitmap_dup (bitmap); } done: if (error) log_err ("hw_set_rss_queues: %U", format_clib_error, error); return error; } int collect_detailed_interface_stats_flag = 0; void collect_detailed_interface_stats_flag_set (void) { collect_detailed_interface_stats_flag = 1; } void collect_detailed_interface_stats_flag_clear (void) { collect_detailed_interface_stats_flag = 0; } static clib_error_t * collect_detailed_interface_stats_cli (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, "expected enable | disable"); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "enable") || unformat (line_input, "on")) collect_detailed_interface_stats_flag_set (); else if (unformat (line_input, "disable") || unformat (line_input, "off")) collect_detailed_interface_stats_flag_clear (); else { error = clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); goto done; } } done: unformat_free (line_input); return error; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (collect_detailed_interface_stats_command, static) = { .path = "interface collect detailed-stats", .short_help = "interface collect detailed-stats <enable|disable>", .function = collect_detailed_interface_stats_cli, }; /* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */