;;; Copyright (c) 2016 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.
;; plugin all-in-1 program
(load-file "./plugin.el")
;; list of clib / vlib / vnet / vpp skeleton files
(load-file "./cli-cmd-skel.el")
(load-file "./config-skel.el")
(load-file "./dual-loop-skel.el")
(load-file "./periodic-skel.el")
(load-file "./pipe-skel.el")
(load-file "./plugin-all-apih-skel.el")
@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 */
}
/*
* Copyright (c) 2018 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.
*/
#ifndef __GBP_CONTRACT_H__
#define __GBP_CONTRACT_H__
#include <plugins/gbp/gbp.h>
#include <plugins/gbp/gbp_types.h>
#define foreach_gbp_contract_error \
_(ALLOW_NO_SCLASS, "allow-no-sclass") \
_(ALLOW_INTRA, "allow-intra-sclass") \
_(ALLOW_A_BIT, "allow-a-bit-set") \
_(ALLOW_SCLASS_1, "allow-sclass-1") \
_(ALLOW_CONTRACT, "allow-contract") \
_(DROP_CONTRACT, "drop-contract") \
_(DROP_ETHER_TYPE, "drop-ether-type") \
_(DROP_NO_CONTRACT, "drop-no-contract") \
_(DROP_NO_DCLASS, "drop-no-dclass") \
_(DROP_NO_RULE, "drop-no-rule")
typedef enum
{
#define _(sym,str) GBP_CONTRACT_ERROR_##sym,
foreach_gbp_contract_error
#undef _
GBP_CONTRACT_N_ERROR,
#define GBP_CONTRACT_N_ERROR GBP_CONTRACT_N_ERROR
} gbp_contract_error_t;
extern char *gbp_contract_error_strings[GBP_CONTRACT_N_ERROR];
/**
* The key for an Contract
*/
typedef struct gbp_contract_key_t_
{
union
{
struct
{
gbp_scope_t gck_scope;
/**
* source and destination EPGs for which the ACL applies
*/
sclass_t gck_src;
sclass_t gck_dst;
};
u64 as_u64;
};
} gbp_contract_key_t;
typedef struct gbp_next_hop_t_
{
fib_node_t gnh_node;
ip46_address_t gnh_ip;
mac_address_t gnh_mac;
index_t gnh_gu;
index_t gnh_bd;
index_t gnh_rd;
u32 gnh_ge;
u32 gnh_sibling;
index_t gnh_ai[FIB_PROTOCOL_IP_MAX];
} gbp_next_hop_t;
#define foreach_gbp_hash_mode \
_(SRC_IP, "src-ip") \
_(DST_IP, "dst-ip") \
_(SYMMETRIC, "symmetric")
typedef enum gbp_hash_mode_t_
{
#define _(v,s) GBP_HASH_MODE_##v,
foreach_gbp_hash_mode
#undef _
} gbp_hash_mode_t;
#define foreach_gbp_rule_action \
_(PERMIT, "permit") \
_(DENY, "deny") \
_(REDIRECT, "redirect")
typedef enum gbp_rule_action_t_
{
#define _(v,s) GBP_RULE_##v,
foreach_gbp_rule_action
#undef _
} gbp_rule_action_t;
#define foreach_gbp_policy_node \
_(L2, "L2") \
_(IP4, "ip4") \
_(IP6, "ip6")
typedef enum gbp_policy_node_t_
{
#define _(v,s) GBP_POLICY_NODE_##v,
foreach_gbp_policy_node
#undef _
} gbp_policy_node_t;
#define GBP_POLICY_N_NODES (GBP_POLICY_NODE_IP6+1)
#define FOR_EACH_GBP_POLICY_NODE(pnode) \
for (pnode = GBP_POLICY_NODE_L2; pnode < GBP_POLICY_N_NODES; pnode++)
typedef struct gbp_rule_t_
{
gbp_rule_action_t gu_action;
gbp_hash_mode_t gu_hash_mode;
index_t *gu_nhs;
/**
* DPO of the load-balance object used to redirect
*/
dpo_id_t gu_dpo[GBP_POLICY_N_NODES][FIB_PROTOCOL_IP_MAX];
} gbp_rule_t;
/**
* A Group Based Policy Contract.
* Determines the ACL that applies to traffic pass between two endpoint groups
*/
typedef struct gbp_contract_t_
{
/**
* source and destination EPGs
*/
gbp_contract_key_t gc_key;
u32 gc_acl_index;
u32 gc_lc_index;
/**
* The ACL to apply for packets from the source to the destination EPG
*/
index_t *gc_rules;
/**
* An ethertype whitelist
*/
u16 *gc_allowed_ethertypes;
} gbp_contract_t;
/**
* EPG src,dst pair to ACL mapping table, aka contract DB
*/
typedef struct gbp_contract_db_t_
{
/**
* We can form a u64 key from the pair, so use a simple hash table
*/
uword *gc_hash;
} gbp_contract_db_t;
extern int gbp_contract_update (gbp_scope_t scope,
sclass_t sclass,
sclass_t dclass,
u32 acl_index,
index_t * rules,
u16 * allowed_ethertypes, u32 * stats_index);
extern int gbp_contract_delete (gbp_scope_t scope, sclass_t sclass,
sclass_t dclass);
extern index_t gbp_rule_alloc (gbp_rule_action_t action,
gbp_hash_mode_t hash_mode, index_t * nhs);
extern void gbp_rule_free (index_t gui);
extern index_t gbp_next_hop_alloc (const ip46_address_t * ip,
index_t grd,
const mac_address_t * mac, index_t gbd);
typedef int (*gbp_contract_cb_t) (gbp_contract_t * gbpe, void *ctx);
extern void gbp_contract_walk (gbp_contract_cb_t bgpe, void *ctx);
extern u8 *format_gbp_rule_action (u8 * s, va_list * args);
extern u8 *format_gbp_contract (u8 * s, va_list * args);
/**
* DP functions and databases
*/
extern gbp_contract_db_t gbp_contract_db;
always_inline index_t
gbp_contract_find (gbp_contract_key_t * key)
{
uword *p;
p = hash_get (gbp_contract_db.gc_hash, key->as_u64);
if (NULL != p)
return (p[0]);
return (INDEX_INVALID);
}
extern gbp_contract_t *gbp_contract_pool;
always_inline gbp_contract_t *
gbp_contract_get (index_t gci)
{
return (pool_elt_at_index (gbp_contract_pool, gci));
}
extern gbp_rule_t *gbp_rule_pool;
always_inline gbp_rule_t *
gbp_rule_get (index_t gui)
{
return (pool_elt_at_index (gbp_rule_pool, gui));
}
extern vlib_combined_counter_main_t gbp_contract_permit_counters;
extern vlib_combined_counter_main_t gbp_contract_drop_counters;
typedef enum
{
GBP_CONTRACT_APPLY_L2,
GBP_CONTRACT_APPLY_IP4,
GBP_CONTRACT_APPLY_IP6,
} gbp_contract_apply_type_t;
static_always_inline gbp_rule_action_t
gbp_contract_apply (vlib_main_t * vm, gbp_main_t * gm,
gbp_contract_key_t * key, vlib_buffer_t * b,
gbp_rule_t ** rule, u32 * intra, u32 * sclass1,
u32 * acl_match, u32 * rule_match,
gbp_contract_error_t * err,
gbp_contract_apply_type_t type)
{
fa_5tuple_opaque_t fa_5tuple;
const gbp_contract_t *contract;
index_t contract_index;
u32 acl_pos, trace_bitmap;
u16 etype;
u8 ip6, action;
*rule = 0;
trace_bitmap = 0;
if (key->gck_src == key->gck_dst)
{
/* intra-epg allowed */
(*intra)++;
*err = GBP_CONTRACT_ERROR_ALLOW_INTRA;
return GBP_RULE_PERMIT;
}
if (1 == key->gck_src || 1 == key->gck_dst)
{
/* sclass 1 allowed */
(*sclass1)++;
*err = GBP_CONTRACT_ERROR_ALLOW_SCLASS_1;
return GBP_RULE_PERMIT;
}
/* look for contract */
contract_index = gbp_contract_find (key);
if (INDEX_INVALID == contract_index)
{
*err = GBP_CONTRACT_ERROR_DROP_NO_CONTRACT;
return GBP_RULE_DENY;
}
contract = gbp_contract_get (contract_index);
*err = GBP_CONTRACT_ERROR_DROP_CONTRACT;
switch (type)
{
case GBP_CONTRACT_APPLY_IP4:
ip6 = 0;
break;
case GBP_CONTRACT_APPLY_IP6:
ip6 = 1;
break;
case GBP_CONTRACT_APPLY_L2:
{
/* check ethertype */
etype =
((u16 *) (vlib_buffer_get_current (b) +
vnet_buffer (b)->l2.l2_len))[-1];
if (~0 == vec_search (contract->gc_allowed_ethertypes, etype))
{
*err = GBP_CONTRACT_ERROR_DROP_ETHER_TYPE;
goto contract_deny;
}
switch (clib_net_to_host_u16 (etype))
{
case ETHERNET_TYPE_IP4:
ip6 = 0;
break;
case ETHERNET_TYPE_IP6:
ip6 = 1;
break;
default:
goto contract_deny;
}
}
break;
}
/* check ACL */
action = 0;
acl_plugin_fill_5tuple_inline (gm->acl_plugin.p_acl_main,
contract->gc_lc_index, b, ip6,
GBP_CONTRACT_APPLY_L2 != type /* input */ ,
GBP_CONTRACT_APPLY_L2 == type /* l2_path */ ,
&fa_5tuple);
acl_plugin_match_5tuple_inline (gm->acl_plugin.p_acl_main,
contract->gc_lc_index, &fa_5tuple, ip6,
&action, &acl_pos, acl_match, rule_match,
&trace_bitmap);
if (action <= 0)
goto contract_deny;
if (PREDICT_FALSE (*rule_match >= vec_len (contract->gc_rules)))
{
*err = GBP_CONTRACT_ERROR_DROP_NO_RULE;
goto contract_deny;
}
*rule = gbp_rule_get (contract->gc_rules[*rule_match]);
switch ((*rule)->gu_action)
{
case GBP_RULE_PERMIT:
case GBP_RULE_REDIRECT:
*err = GBP_CONTRACT_ERROR_ALLOW_CONTRACT;
vlib_increment_combined_counter (&gbp_contract_permit_counters,
vm->thread_index, contract_index, 1,
vlib_buffer_length_in_chain (vm, b));
return (*rule)->gu_action;
case GBP_RULE_DENY:
break;
}
contract_deny:
vlib_increment_combined_counter (&gbp_contract_drop_counters,
vm->thread_index, contract_index, 1,
vlib_buffer_length_in_chain (vm, b));
return GBP_RULE_DENY;
}
#endif /* __GBP_CONTRACT_H__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/