GBP: add allowed ethertypes to contracts 75/16575/6
authorNeale Ranns <nranns@cisco.com>
Thu, 20 Dec 2018 20:03:59 +0000 (12:03 -0800)
committerNeale Ranns <nranns@cisco.com>
Fri, 21 Dec 2018 18:12:25 +0000 (18:12 +0000)
Change-Id: I74782d3b9b71a071bb500c34866a017b8ee15767
Signed-off-by: Neale Ranns <nranns@cisco.com>
13 files changed:
extras/vom/vom/gbp_contract.cpp
extras/vom/vom/gbp_contract.hpp
extras/vom/vom/gbp_contract_cmds.cpp
extras/vom/vom/gbp_contract_cmds.hpp
extras/vom/vom/gbp_rule.cpp
extras/vom/vom/gbp_rule.hpp
src/plugins/gbp/gbp.api
src/plugins/gbp/gbp_api.c
src/plugins/gbp/gbp_contract.c
src/plugins/gbp/gbp_contract.h
src/plugins/gbp/gbp_policy.c
test/test_gbp.py
test/vpp_papi_provider.py

index 87b5ed8..6cd2fad 100644 (file)
@@ -26,11 +26,15 @@ gbp_contract::event_handler gbp_contract::m_evh;
 
 gbp_contract::gbp_contract(epg_id_t src_epg_id,
                            epg_id_t dst_epg_id,
-                           const ACL::l3_list& acl)
+                           const ACL::l3_list& acl,
+                           const gbp_rules_t& rules,
+                           const ethertype_set_t& allowed_ethertypes)
   : m_hw(false)
   , m_src_epg_id(src_epg_id)
   , m_dst_epg_id(dst_epg_id)
   , m_acl(acl.singular())
+  , m_gbp_rules(rules)
+  , m_allowed_ethertypes(allowed_ethertypes)
 {
 }
 
@@ -39,6 +43,8 @@ gbp_contract::gbp_contract(const gbp_contract& gbpc)
   , m_src_epg_id(gbpc.m_src_epg_id)
   , m_dst_epg_id(gbpc.m_dst_epg_id)
   , m_acl(gbpc.m_acl)
+  , m_gbp_rules(gbpc.m_gbp_rules)
+  , m_allowed_ethertypes(gbpc.m_allowed_ethertypes)
 {
 }
 
@@ -77,7 +83,8 @@ gbp_contract::replay()
 {
   if (m_hw) {
     HW::enqueue(new gbp_contract_cmds::create_cmd(
-      m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules));
+      m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules,
+      m_allowed_ethertypes));
   }
 }
 
@@ -99,12 +106,6 @@ gbp_contract::to_string() const
   return (s.str());
 }
 
-void
-gbp_contract::set_gbp_rules(const gbp_contract::gbp_rules_t& gbp_rules)
-{
-  m_gbp_rules = gbp_rules;
-}
-
 void
 gbp_contract::update(const gbp_contract& r)
 {
@@ -113,7 +114,8 @@ gbp_contract::update(const gbp_contract& r)
    */
   if (rc_t::OK != m_hw.rc()) {
     HW::enqueue(new gbp_contract_cmds::create_cmd(
-      m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules));
+      m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules,
+      m_allowed_ethertypes));
   }
 }
 
@@ -169,31 +171,44 @@ gbp_contract::event_handler::handle_populate(const client_db::key_t& key)
       ACL::l3_list::find(payload.contract.acl_index);
 
     if (acl) {
-      gbp_contract gbpc(payload.contract.src_epg, payload.contract.dst_epg,
-                        *acl);
-      OM::commit(key, gbpc);
-      if (payload.contract.n_rules) {
-        gbp_contract::gbp_rules_t rules;
-        for (u8 i = 0; i < payload.contract.n_rules; i++) {
-          const gbp_rule::action_t action =
-            gbp_rule::action_t::from_int(payload.contract.rules[i].action);
-          const gbp_rule::hash_mode_t hm = gbp_rule::hash_mode_t::from_int(
-            payload.contract.rules[i].nh_set.hash_mode);
-          gbp_rule::next_hops_t nhs;
-          for (u8 j = 0; j < payload.contract.rules[i].nh_set.n_nhs; j++) {
-            gbp_rule::next_hop_t nh(
-              from_api(payload.contract.rules[i].nh_set.nhs[j].ip),
-              from_api(payload.contract.rules[i].nh_set.nhs[j].mac),
-              payload.contract.rules[i].nh_set.nhs[j].bd_id,
-              payload.contract.rules[i].nh_set.nhs[j].rd_id);
-            nhs.insert(nh);
-          }
-          gbp_rule::next_hop_set_t next_hop_set(hm, nhs);
-          gbp_rule gr(i, next_hop_set, action);
-          rules.insert(gr);
+      gbp_contract::gbp_rules_t rules;
+
+      for (uint8_t i = 0; i < payload.contract.n_rules; i++) {
+        const gbp_rule::action_t action =
+          gbp_rule::action_t::from_int(payload.contract.rules[i].action);
+        const gbp_rule::hash_mode_t hm = gbp_rule::hash_mode_t::from_int(
+          payload.contract.rules[i].nh_set.hash_mode);
+        gbp_rule::next_hops_t nhs;
+        for (u8 j = 0; j < payload.contract.rules[i].nh_set.n_nhs; j++) {
+          gbp_rule::next_hop_t nh(
+            from_api(payload.contract.rules[i].nh_set.nhs[j].ip),
+            from_api(payload.contract.rules[i].nh_set.nhs[j].mac),
+            payload.contract.rules[i].nh_set.nhs[j].bd_id,
+            payload.contract.rules[i].nh_set.nhs[j].rd_id);
+          nhs.insert(nh);
         }
-        gbpc.set_gbp_rules(rules);
+        gbp_rule::next_hop_set_t next_hop_set(hm, nhs);
+        gbp_rule gr(i, next_hop_set, action);
+        rules.insert(gr);
+      }
+
+      ethertype_set_t allowed_ethertypes;
+      u8 *data, n_et;
+      u16* et;
+
+      data = (((u8*)&payload.contract.n_ether_types) +
+              (sizeof(payload.contract.rules[0]) * payload.contract.n_rules));
+      n_et = *data;
+      et = (u16*)(++data);
+
+      for (uint8_t i = 0; i < n_et; i++) {
+        allowed_ethertypes.insert(ethertype_t::from_numeric_val(et[i]));
       }
+
+      gbp_contract gbpc(payload.contract.src_epg, payload.contract.dst_epg,
+                        *acl, rules, allowed_ethertypes);
+      OM::commit(key, gbpc);
+
       VOM_LOG(log_level_t::DEBUG) << "read: " << gbpc.to_string();
     }
   }
index 53f8f36..e517a3d 100644 (file)
@@ -41,12 +41,19 @@ public:
    */
   typedef std::pair<epg_id_t, epg_id_t> key_t;
 
+  /**
+   * A set of allowed ethertypes
+   */
+  typedef std::set<ethertype_t> ethertype_set_t;
+
   /**
    * Construct a GBP contract
    */
   gbp_contract(epg_id_t src_epg_id,
                epg_id_t dst_epg_id,
-               const ACL::l3_list& acl);
+               const ACL::l3_list& acl,
+               const gbp_rules_t& gpb_rules,
+               const ethertype_set_t& allowed_ethertypes);
 
   /**
    * Copy Construct
@@ -93,11 +100,6 @@ public:
    */
   std::string to_string() const;
 
-  /**
-   * Set gbp_rules in case of Redirect Contract
-   */
-  void set_gbp_rules(const gbp_rules_t& gbp_rules);
-
 private:
   /**
    * Class definition for listeners to OM events
@@ -184,6 +186,11 @@ private:
    */
   gbp_rules_t m_gbp_rules;
 
+  /**
+   * the set of Ether-types allowed by this contract
+   */
+  ethertype_set_t m_allowed_ethertypes;
+
   /**
    * A map of all bridge_domains
    */
index 8b15e8c..7c42fc6 100644 (file)
@@ -23,12 +23,14 @@ create_cmd::create_cmd(HW::item<bool>& item,
                        epg_id_t src_epg_id,
                        epg_id_t dst_epg_id,
                        const handle_t& acl,
-                       const gbp_contract::gbp_rules_t& gbp_rules)
+                       const gbp_contract::gbp_rules_t& gbp_rules,
+                       const gbp_contract::ethertype_set_t& allowed_ethertypes)
   : rpc_cmd(item)
   , m_src_epg_id(src_epg_id)
   , m_dst_epg_id(dst_epg_id)
   , m_acl(acl)
   , m_gbp_rules(gbp_rules)
+  , m_allowed_ethertypes(allowed_ethertypes)
 {
 }
 
@@ -37,58 +39,69 @@ create_cmd::operator==(const create_cmd& other) const
 {
   return ((m_acl == other.m_acl) && (m_src_epg_id == other.m_src_epg_id) &&
           (m_dst_epg_id == other.m_dst_epg_id) &&
-          (m_gbp_rules == other.m_gbp_rules));
+          (m_gbp_rules == other.m_gbp_rules) &&
+          (m_allowed_ethertypes == other.m_allowed_ethertypes));
 }
 
 rc_t
 create_cmd::issue(connection& con)
 {
-  u8 size = m_gbp_rules.empty() ? 1 : m_gbp_rules.size();
-  msg_t req(con.ctx(), size, std::ref(*this));
+  size_t n_rules = m_gbp_rules.size();
+  size_t n_et_rules = 0;
+
+  msg_t req(con.ctx(), n_rules, n_et_rules, std::ref(*this));
 
   auto& payload = req.get_request().get_payload();
   payload.is_add = 1;
   payload.contract.acl_index = m_acl.value();
   payload.contract.src_epg = m_src_epg_id;
   payload.contract.dst_epg = m_dst_epg_id;
-  if (size > 1) {
-    u32 ii = 0;
-    auto it = m_gbp_rules.cbegin();
-    payload.contract.n_rules = m_gbp_rules.size();
-    while (it != m_gbp_rules.cend()) {
-      if (it->action() == gbp_rule::action_t::REDIRECT)
-        payload.contract.rules[ii].action = GBP_API_RULE_REDIRECT;
-      else if (it->action() == gbp_rule::action_t::PERMIT)
-        payload.contract.rules[ii].action = GBP_API_RULE_PERMIT;
-      else
-        payload.contract.rules[ii].action = GBP_API_RULE_DENY;
-
-      if (it->nhs().getHashMode() == gbp_rule::hash_mode_t::SYMMETRIC)
-        payload.contract.rules[ii].nh_set.hash_mode =
-          GBP_API_HASH_MODE_SYMMETRIC;
-      else if (it->nhs().getHashMode() == gbp_rule::hash_mode_t::SRC_IP)
-        payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SRC_IP;
-      else
-        payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_DST_IP;
-
-      const gbp_rule::next_hops_t& next_hops = it->nhs().getNextHops();
-      u8 jj = 0, nh_size = (next_hops.size() > 8) ? 8 : next_hops.size();
-      auto nh_it = next_hops.cbegin();
-
-      payload.contract.rules[ii].nh_set.n_nhs = nh_size;
-      while (jj < nh_size) {
-        to_api(nh_it->getIp(), payload.contract.rules[ii].nh_set.nhs[jj].ip);
-        to_api(nh_it->getMac(), payload.contract.rules[ii].nh_set.nhs[jj].mac);
-        payload.contract.rules[ii].nh_set.nhs[jj].bd_id = nh_it->getBdId();
-        payload.contract.rules[ii].nh_set.nhs[jj].rd_id = nh_it->getRdId();
-        ++nh_it;
-        ++jj;
-      }
-
-      ++it;
-      ++ii;
+
+  uint32_t ii = 0;
+  payload.contract.n_rules = n_rules;
+
+  for (auto rule : m_gbp_rules) {
+    if (rule.action() == gbp_rule::action_t::REDIRECT)
+      payload.contract.rules[ii].action = GBP_API_RULE_REDIRECT;
+    else if (rule.action() == gbp_rule::action_t::PERMIT)
+      payload.contract.rules[ii].action = GBP_API_RULE_PERMIT;
+    else
+      payload.contract.rules[ii].action = GBP_API_RULE_DENY;
+
+    if (rule.nhs().hash_mode() == gbp_rule::hash_mode_t::SYMMETRIC)
+      payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SYMMETRIC;
+    else if (rule.nhs().hash_mode() == gbp_rule::hash_mode_t::SRC_IP)
+      payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SRC_IP;
+    else
+      payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_DST_IP;
+
+    const gbp_rule::next_hops_t& next_hops = rule.nhs().next_hops();
+    uint8_t jj = 0, nh_size = (next_hops.size() > 8) ? 8 : next_hops.size();
+
+    payload.contract.rules[ii].nh_set.n_nhs = nh_size;
+    for (auto nh : next_hops) {
+      to_api(nh.getIp(), payload.contract.rules[ii].nh_set.nhs[jj].ip);
+      to_api(nh.getMac(), payload.contract.rules[ii].nh_set.nhs[jj].mac);
+      payload.contract.rules[ii].nh_set.nhs[jj].bd_id = nh.getBdId();
+      payload.contract.rules[ii].nh_set.nhs[jj].rd_id = nh.getRdId();
+      jj++;
     }
+    ++ii;
   }
+
+  u8* data;
+  u16* et;
+
+  data = (((u8*)&payload.contract.n_ether_types) +
+          (sizeof(payload.contract.rules[0]) * payload.contract.n_rules));
+  *data = m_allowed_ethertypes.size();
+  et = (u16*)(++data);
+  ii = 0;
+  for (auto tt : m_allowed_ethertypes) {
+    et[ii] = tt.value();
+    ii++;
+  }
+
   VAPI_CALL(req.execute());
 
   return (wait());
@@ -124,7 +137,7 @@ delete_cmd::operator==(const delete_cmd& other) const
 rc_t
 delete_cmd::issue(connection& con)
 {
-  msg_t req(con.ctx(), 1, std::ref(*this));
+  msg_t req(con.ctx(), 0, 0, std::ref(*this));
 
   auto& payload = req.get_request().get_payload();
   payload.is_add = 0;
index 4f921f6..476a594 100644 (file)
@@ -37,7 +37,8 @@ public:
              epg_id_t src_epg_id,
              epg_id_t dst_epg_id,
              const handle_t& acl,
-             const gbp_contract::gbp_rules_t& gbp_rules);
+             const gbp_contract::gbp_rules_t& gbp_rules,
+             const gbp_contract::ethertype_set_t& allowed_ethertypes);
 
   /**
    * Issue the command to VPP/HW
@@ -59,6 +60,7 @@ private:
   const epg_id_t m_dst_epg_id;
   const handle_t m_acl;
   const gbp_contract::gbp_rules_t& m_gbp_rules;
+  const gbp_contract::ethertype_set_t& m_allowed_ethertypes;
 };
 
 /**
index 7aa7990..48c59b1 100644 (file)
@@ -105,6 +105,12 @@ gbp_rule::next_hop_set_t::next_hop_set_t(const gbp_rule::hash_mode_t& hm,
 {
 }
 
+gbp_rule::next_hop_set_t::next_hop_set_t(const hash_mode_t& hm)
+  : m_hm(hm)
+  , m_nhs()
+{
+}
+
 std::string
 gbp_rule::next_hop_set_t::to_string() const
 {
@@ -128,13 +134,13 @@ gbp_rule::next_hop_set_t::operator==(const next_hop_set_t& nhs) const
 }
 
 const gbp_rule::hash_mode_t&
-gbp_rule::next_hop_set_t::getHashMode() const
+gbp_rule::next_hop_set_t::hash_mode() const
 {
   return m_hm;
 }
 
 const gbp_rule::next_hops_t&
-gbp_rule::next_hop_set_t::getNextHops() const
+gbp_rule::next_hop_set_t::next_hops() const
 {
   return m_nhs;
 }
@@ -168,6 +174,13 @@ gbp_rule::gbp_rule(uint32_t priority,
 {
 }
 
+gbp_rule::gbp_rule(uint32_t priority, const gbp_rule::action_t& a)
+  : m_priority(priority)
+  , m_nhs()
+  , m_action(a)
+{
+}
+
 bool
 gbp_rule::operator<(const gbp_rule& other) const
 {
@@ -193,12 +206,6 @@ gbp_rule::to_string() const
   return (s.str());
 }
 
-uint32_t
-gbp_rule::priority() const
-{
-  return m_priority;
-}
-
 const gbp_rule::action_t&
 gbp_rule::action() const
 {
index bda0409..04301da 100644 (file)
@@ -147,6 +147,7 @@ public:
      * Constructor for next_hop_set_t
      */
     next_hop_set_t(const hash_mode_t& hm, next_hops_t& nhs);
+    next_hop_set_t(const hash_mode_t& hm = hash_mode_t::SYMMETRIC);
 
     /**
      * Destructor for next_hop_set_t
@@ -166,12 +167,12 @@ public:
     /**
      * get the hash mode
      */
-    const hash_mode_t& getHashMode(void) const;
+    const hash_mode_t& hash_mode(void) const;
 
     /**
      * get the set of next hops
      */
-    const next_hops_t& getNextHops(void) const;
+    const next_hops_t& next_hops(void) const;
 
   private:
     /**
@@ -218,6 +219,7 @@ public:
    * Construct a new object matching the desried state
    */
   gbp_rule(uint32_t priority, const next_hop_set_t& nhs, const action_t& a);
+  gbp_rule(uint32_t priority, const action_t& a);
 
   /**
    * Copy Constructor
@@ -235,8 +237,8 @@ public:
   std::string to_string() const;
 
   /**
-   * less-than operator
-   */
+  * less-than operator
+  */
   bool operator<(const gbp_rule& rule) const;
 
   /**
@@ -247,7 +249,6 @@ public:
   /**
    * Getters
    */
-  uint32_t priority() const;
   const next_hop_set_t& nhs() const;
   const action_t& action() const;
 
index bf7c167..e96cb50 100644 (file)
@@ -295,6 +295,8 @@ typedef gbp_contract
   u32 acl_index;
   u8  n_rules;
   vl_api_gbp_rule_t rules[n_rules];
+  u8 n_ether_types;
+  u16 allowed_ethertypes[n_ether_types];
 };
 
 autoreply define gbp_contract_add_del
index 74355d1..8ea5a0e 100644 (file)
@@ -924,8 +924,11 @@ static void
 vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
 {
   vl_api_gbp_contract_add_del_reply_t *rmp;
+  u16 *allowed_ethertypes;
   index_t *rules;
-  int rv = 0;
+  int ii, rv = 0;
+  u8 *data, n_et;
+  u16 *et;
 
   if (mp->is_add)
     {
@@ -934,9 +937,28 @@ vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
       if (0 != rv)
        goto out;
 
+      allowed_ethertypes = NULL;
+
+      /*
+       * move past the variable legnth array of rules to get to the
+       * allowed ether types
+       */
+      data = (((u8 *) & mp->contract.n_ether_types) +
+             (sizeof (mp->contract.rules[0]) * mp->contract.n_rules));
+      n_et = *data;
+      et = (u16 *) (++data);
+      vec_validate (allowed_ethertypes, n_et - 1);
+
+      for (ii = 0; ii < n_et; ii++)
+       {
+         /* leave the ether types in network order */
+         allowed_ethertypes[ii] = et[ii];
+       }
+
       rv = gbp_contract_update (ntohs (mp->contract.src_epg),
                                ntohs (mp->contract.dst_epg),
-                               ntohl (mp->contract.acl_index), rules);
+                               ntohl (mp->contract.acl_index),
+                               rules, allowed_ethertypes);
     }
   else
     rv = gbp_contract_delete (ntohs (mp->contract.src_epg),
index ee12a76..f7b8b64 100644 (file)
@@ -434,7 +434,8 @@ gbp_contract_mk_lbs (index_t * guis)
 
 int
 gbp_contract_update (epg_id_t src_epg,
-                    epg_id_t dst_epg, u32 acl_index, index_t * rules)
+                    epg_id_t dst_epg,
+                    u32 acl_index, index_t * rules, u16 * allowed_ethertypes)
 {
   gbp_main_t *gm = &gbp_main;
   u32 *acl_vec = NULL;
@@ -462,6 +463,7 @@ gbp_contract_update (epg_id_t src_epg,
       gbp_contract_rules_free (gc->gc_rules);
       gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index);
       gc->gc_rules = NULL;
+      vec_free (gc->gc_allowed_ethertypes);
     }
   else
     {
@@ -474,6 +476,7 @@ gbp_contract_update (epg_id_t src_epg,
   GBP_CONTRACT_DBG ("update: %U", format_gbp_contract, gci);
 
   gc->gc_rules = rules;
+  gc->gc_allowed_ethertypes = allowed_ethertypes;
   gbp_contract_resolve (gc->gc_rules);
   gbp_contract_mk_lbs (gc->gc_rules);
 
@@ -506,6 +509,7 @@ gbp_contract_delete (epg_id_t src_epg, epg_id_t dst_epg)
 
       gbp_contract_rules_free (gc->gc_rules);
       gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index);
+      vec_free (gc->gc_allowed_ethertypes);
 
       hash_unset (gbp_contract_db.gc_hash, key.as_u32);
       pool_put (gbp_contract_pool, gc);
@@ -561,7 +565,7 @@ gbp_contract_cli (vlib_main_t * vm,
 
   if (add)
     {
-      gbp_contract_update (src_epg_id, dst_epg_id, acl_index, NULL);
+      gbp_contract_update (src_epg_id, dst_epg_id, acl_index, NULL, NULL);
     }
   else
     {
@@ -604,6 +608,7 @@ format_gbp_contract (u8 * s, va_list * args)
   index_t gci = va_arg (*args, index_t);
   gbp_contract_t *gc;
   index_t *gui;
+  u16 *et;
 
   gc = gbp_contract_get (gci);
 
@@ -615,6 +620,14 @@ format_gbp_contract (u8 * s, va_list * args)
     s = format (s, "\n    %d: %U", *gui, format_gbp_rule, *gui);
   }
 
+  s = format (s, "\n    allowed-ethertypes:[");
+  vec_foreach (et, gc->gc_allowed_ethertypes)
+  {
+    int host_et = clib_net_to_host_u16 (*et);
+    s = format (s, "0x%x, ", host_et);
+  }
+  s = format (s, "]");
+
   return (s);
 }
 
index bd7d833..876c10f 100644 (file)
@@ -120,6 +120,11 @@ typedef struct gbp_contract_t_
    * 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;
 
 /**
@@ -135,7 +140,8 @@ typedef struct gbp_contract_db_t_
 
 extern int gbp_contract_update (epg_id_t src_epg,
                                epg_id_t dst_epg,
-                               u32 acl_index, index_t * rules);
+                               u32 acl_index,
+                               index_t * rules, u16 * allowed_ethertypes);
 extern int gbp_contract_delete (epg_id_t src_epg, epg_id_t dst_epg);
 
 extern index_t gbp_rule_alloc (gbp_rule_action_t action,
index 3b204ff..174223e 100644 (file)
@@ -106,6 +106,19 @@ gbp_rule_l2_redirect (const gbp_rule_t * gu, vlib_buffer_t * b0)
   return (dpo->dpoi_next_node);
 }
 
+always_inline u8
+gbp_policy_is_ethertype_allowed (const gbp_contract_t * gc0, u16 ethertype)
+{
+  u16 *et;
+
+  vec_foreach (et, gc0->gc_allowed_ethertypes)
+  {
+    if (*et == ethertype)
+      return (1);
+  }
+  return (0);
+}
+
 static uword
 gbp_policy_inline (vlib_main_t * vm,
                   vlib_node_runtime_t * node,
@@ -130,9 +143,9 @@ gbp_policy_inline (vlib_main_t * vm,
        {
          const ethernet_header_t *h0;
          const gbp_endpoint_t *ge0;
+         const gbp_contract_t *gc0;
          gbp_policy_next_t next0;
          gbp_contract_key_t key0;
-         gbp_contract_t *gc0;
          u32 bi0, sw_if_index0;
          vlib_buffer_t *b0;
          index_t gci0;
@@ -204,66 +217,84 @@ gbp_policy_inline (vlib_main_t * vm,
 
                  if (INDEX_INVALID != gci0)
                    {
+                     u32 rule_match_p0, trace_bitmap0;
                      fa_5tuple_opaque_t pkt_5tuple0;
-                     u8 action0 = 0;
                      u32 acl_pos_p0, acl_match_p0;
-                     u32 rule_match_p0, trace_bitmap0;
-                     u8 *h0, l2_len0;
+                     u8 is_ip60, l2_len0, action0;
+                     const gbp_rule_t *gu;
                      u16 ether_type0;
-                     u8 is_ip60 = 0;
+                     const u8 *h0;
 
+                     action0 = 0;
                      gc0 = gbp_contract_get (gci0);
                      l2_len0 = vnet_buffer (b0)->l2.l2_len;
                      h0 = vlib_buffer_get_current (b0);
 
-                     ether_type0 =
-                       clib_net_to_host_u16 (*(u16 *) (h0 + l2_len0 - 2));
-
-                     is_ip60 = (ether_type0 == ETHERNET_TYPE_IP6) ? 1 : 0;
-                     /*
-                      * tests against the ACL
-                      */
-                     acl_plugin_fill_5tuple_inline (gm->
-                                                    acl_plugin.p_acl_main,
-                                                    gc0->gc_lc_index, b0,
-                                                    is_ip60,
-                                                    /* is_input */ 0,
-                                                    /* is_l2_path */ 1,
-                                                    &pkt_5tuple0);
-                     acl_plugin_match_5tuple_inline (gm->
-                                                     acl_plugin.p_acl_main,
-                                                     gc0->gc_lc_index,
-                                                     &pkt_5tuple0, is_ip60,
-                                                     &action0, &acl_pos_p0,
-                                                     &acl_match_p0,
-                                                     &rule_match_p0,
-                                                     &trace_bitmap0);
-
-                     if (action0 > 0)
-                       {
-                         gbp_rule_t *gu;
+                     ether_type0 = *(u16 *) (h0 + l2_len0 - 2);
 
-                         vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
-                         gu = gbp_rule_get (gc0->gc_rules[rule_match_p0]);
+                     if (!gbp_policy_is_ethertype_allowed (gc0, ether_type0))
+                       {
+                         /*
+                          * black list model so drop
+                          */
+                         goto trace;
+                       }
 
-                         switch (gu->gu_action)
+                     if ((ether_type0 ==
+                          clib_net_to_host_u16 (ETHERNET_TYPE_IP6))
+                         || (ether_type0 ==
+                             clib_net_to_host_u16 (ETHERNET_TYPE_IP4)))
+                       {
+                         is_ip60 =
+                           (ether_type0 ==
+                            clib_net_to_host_u16 (ETHERNET_TYPE_IP6)) ? 1 :
+                           0;
+                         /*
+                          * tests against the ACL
+                          */
+                         acl_plugin_fill_5tuple_inline (gm->
+                                                        acl_plugin.p_acl_main,
+                                                        gc0->gc_lc_index, b0,
+                                                        is_ip60,
+                                                        /* is_input */ 0,
+                                                        /* is_l2_path */ 1,
+                                                        &pkt_5tuple0);
+                         acl_plugin_match_5tuple_inline (gm->
+                                                         acl_plugin.p_acl_main,
+                                                         gc0->gc_lc_index,
+                                                         &pkt_5tuple0,
+                                                         is_ip60, &action0,
+                                                         &acl_pos_p0,
+                                                         &acl_match_p0,
+                                                         &rule_match_p0,
+                                                         &trace_bitmap0);
+
+                         if (action0 > 0)
                            {
-                           case GBP_RULE_PERMIT:
-                             next0 = vnet_l2_feature_next
-                               (b0,
-                                gpm->l2_output_feat_next
-                                [is_port_based],
-                                (is_port_based ?
-                                 L2OUTPUT_FEAT_GBP_POLICY_PORT :
-                                 L2OUTPUT_FEAT_GBP_POLICY_MAC));
-                             break;
-                           case GBP_RULE_DENY:
-                             ASSERT (0);
-                             next0 = 0;
-                             break;
-                           case GBP_RULE_REDIRECT:
-                             next0 = gbp_rule_l2_redirect (gu, b0);
-                             break;
+                             vnet_buffer2 (b0)->gbp.flags |=
+                               VXLAN_GBP_GPFLAGS_A;
+                             gu =
+                               gbp_rule_get (gc0->gc_rules[rule_match_p0]);
+
+                             switch (gu->gu_action)
+                               {
+                               case GBP_RULE_PERMIT:
+                                 next0 = vnet_l2_feature_next
+                                   (b0,
+                                    gpm->l2_output_feat_next
+                                    [is_port_based],
+                                    (is_port_based ?
+                                     L2OUTPUT_FEAT_GBP_POLICY_PORT :
+                                     L2OUTPUT_FEAT_GBP_POLICY_MAC));
+                                 break;
+                               case GBP_RULE_DENY:
+                                 ASSERT (0);
+                                 next0 = 0;
+                                 break;
+                               case GBP_RULE_REDIRECT:
+                                 next0 = gbp_rule_l2_redirect (gu, b0);
+                                 break;
+                               }
                            }
                        }
                    }
index 2297c49..718bbb4 100644 (file)
@@ -24,6 +24,7 @@ from scapy.layers.inet6 import IPv6, ICMPv6ND_NS,  ICMPv6NDOptSrcLLAddr, \
     ICMPv6ND_NA
 from scapy.utils6 import in6_getnsma, in6_getnsmac
 from scapy.layers.vxlan import VXLAN
+from scapy.data import ETH_P_IP, ETH_P_IPV6
 
 from socket import AF_INET, AF_INET6
 from scapy.utils import inet_pton, inet_ntop
@@ -438,12 +439,14 @@ class VppGbpContract(VppObject):
     GBP Contract
     """
 
-    def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
+    def __init__(self, test, src_epg, dst_epg, acl_index,
+                 rules, allowed_ethertypes):
         self._test = test
         self.acl_index = acl_index
         self.src_epg = src_epg
         self.dst_epg = dst_epg
         self.rules = rules
+        self.allowed_ethertypes = allowed_ethertypes
 
     def add_vpp_config(self):
         rules = []
@@ -454,7 +457,8 @@ class VppGbpContract(VppObject):
             self.src_epg,
             self.dst_epg,
             self.acl_index,
-            rules)
+            rules,
+            self.allowed_ethertypes)
         self._test.registry.register(self, self._test.logger)
 
     def remove_vpp_config(self):
@@ -463,7 +467,7 @@ class VppGbpContract(VppObject):
             self.src_epg,
             self.dst_epg,
             self.acl_index,
-            [])
+            [], [])
 
     def __str__(self):
         return self.object_id()
@@ -1140,7 +1144,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c1.add_vpp_config()
 
         self.send_and_expect_bridged(eps[0].itf,
@@ -1159,8 +1164,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
-
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c2.add_vpp_config()
 
         self.send_and_expect_bridged(eps[0].itf,
@@ -1170,6 +1175,15 @@ class TestGBP(VppTestCase):
                                      pkt_inter_epg_221_to_220 * 65,
                                      eps[0].itf)
 
+        #
+        # the contract does not allow non-IP
+        #
+        pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
+                                                 dst=self.pg2.remote_mac) /
+                                           ARP())
+        self.send_and_assert_no_replies(eps[0].itf,
+                                        pkt_non_ip_inter_epg_220_to_221 * 17)
+
         #
         # check that inter group is still disabled for the groups
         # not in the contract.
@@ -1187,8 +1201,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
-
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c3.add_vpp_config()
 
         self.logger.info(self.vapi.cli("sh gbp contract"))
@@ -1292,8 +1306,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
-
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c4.add_vpp_config()
 
         self.send_and_expect_natted(eps[0].itf,
@@ -1333,8 +1347,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
-
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c5.add_vpp_config()
 
         self.send_and_expect_unnatted(self.pg7,
@@ -1739,8 +1753,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
-
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c1.add_vpp_config()
 
         for l in learnt:
@@ -2654,7 +2668,8 @@ class TestGBP(VppTestCase):
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c1.add_vpp_config()
 
         c2 = VppGbpContract(
@@ -2672,7 +2687,8 @@ class TestGBP(VppTestCase):
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c2.add_vpp_config()
 
         #
@@ -2784,7 +2800,8 @@ class TestGBP(VppTestCase):
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c1.add_vpp_config()
 
         c2 = VppGbpContract(
@@ -2802,7 +2819,8 @@ class TestGBP(VppTestCase):
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c2.add_vpp_config()
 
         #
@@ -2852,21 +2870,22 @@ class TestGBP(VppTestCase):
                Raw('\xa5' * 100))]
 
         c3 = VppGbpContract(
-             self, 220, 221, acl_index,
-             [VppGbpContractRule(
+            self, 220, 221, acl_index,
+            [VppGbpContractRule(
+                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                       sep1.ip4, sep1.epg.rd),
+                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                       sep2.ip4, sep2.epg.rd)]),
+             VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
                  VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
-                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
-                                        sep1.ip4, sep1.epg.rd),
-                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
-                                        sep2.ip4, sep2.epg.rd)]),
-              VppGbpContractRule(
-                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
-                  VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
-                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
-                                         sep3.ip6, sep3.epg.rd),
-                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                         sep4.ip6, sep4.epg.rd)])])
+                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                        sep3.ip6, sep3.epg.rd),
+                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c3.add_vpp_config()
 
         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
@@ -2892,7 +2911,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c4.add_vpp_config()
 
         p = (Ether(src=self.pg7.remote_mac,
@@ -2977,7 +2997,8 @@ class TestGBP(VppTestCase):
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
+                                        sep4.ip6, sep4.epg.rd)])],
+            [ETH_P_IP, ETH_P_IPV6])
         c5.add_vpp_config()
 
         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
@@ -3273,7 +3294,8 @@ class TestGBP(VppTestCase):
                 []),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
-                 [])])
+                 [])],
+            [ETH_P_IP, ETH_P_IPV6])
         c1.add_vpp_config()
 
         rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
index 55bf7ed..828f030 100644 (file)
@@ -3713,7 +3713,8 @@ class VppPapiProvider(object):
         return self.api(self.papi.gbp_subnet_dump,
                         {'_no_type_conversion': True})
 
-    def gbp_contract_add_del(self, is_add, src_epg, dst_epg, acl_index, rules):
+    def gbp_contract_add_del(self, is_add, src_epg, dst_epg, acl_index,
+                             rules, allowed_ethertypes):
         """ GBP contract Add/Del """
         return self.api(self.papi.gbp_contract_add_del,
                         {'is_add': is_add,
@@ -3722,7 +3723,9 @@ class VppPapiProvider(object):
                              'src_epg': src_epg,
                              'dst_epg': dst_epg,
                              'n_rules': len(rules),
-                             'rules': rules}})
+                             'rules': rules,
+                             'n_ether_types': len(allowed_ethertypes),
+                             'allowed_ethertypes': allowed_ethertypes}})
 
     def gbp_contract_dump(self):
         """ GBP contract Dump """