/* -*- C++ -*-; c-basic-offset: 4; indent-tabs-mode: nil */ /* * Copyright (c) 2018 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ #include #include #include #include #include #include #include #include #include #include #include "VppEndPointGroupManager.hpp" #include "VppExtItfManager.hpp" #include "VppLog.hpp" #include "VppRouteManager.hpp" #include "VppUtil.hpp" using namespace VOM; namespace VPP { ExtItfManager::ExtItfManager(Runtime &runtime) : m_runtime(runtime) { } void ExtItfManager::handle_update(const opflex::modb::URI &uri) { OM::mark_n_sweep ms(uri.toString()); const std::string &uuid = uri.toString(); boost::optional> ext_itf = modelgbp::gbp::ExternalInterface::resolve( m_runtime.agent.getFramework(), uri); if (!ext_itf) { VLOGD << "External-Interface; delete: " << uri; return; } VLOGD << "External-Interface; update: " << uri; boost::optional> op_bd = m_runtime.policy_manager().getBDForExternalInterface(uri); if (!op_bd) { VLOGE << "External-Interface; no ExternalBridgeDomain: " << uri; return; } boost::optional> op_rd = m_runtime.policy_manager().getRDForExternalInterface(uri); if (!op_rd) { VLOGE << "External-Interface; no RouteDomain: " << uri; return; } uint32_t rd_id = m_runtime.id_gen.get( modelgbp::gbp::RoutingDomain::CLASS_ID, op_rd.get()->getURI()); route_domain rd(rd_id); OM::write(uuid, rd); uint32_t bd_id = m_runtime.id_gen.get(modelgbp::gbp::BridgeDomain::CLASS_ID, op_bd.get()->getURI()); bridge_domain bd(bd_id, bridge_domain::learning_mode_t::OFF); OM::write(uuid, bd); /* * Create a BVI interface for the EPG and add it to the bridge-domain */ std::shared_ptr bvi = EndPointGroupManager::mk_bvi( m_runtime, uuid, bd, rd, mac_from_modb(ext_itf.get()->getMac())); /* * Add the mcast tunnels for flooding */ boost::optional maddr = m_runtime.policy_manager().getBDMulticastIPForExternalInterface(uri); boost::optional bd_vnid = m_runtime.policy_manager().getBDVnidForExternalInterface(uri); boost::optional rd_vnid = m_runtime.policy_manager().getRDVnidForExternalInterface(uri); if (!(rd_vnid && bd_vnid && maddr)) { VLOGE << "External-Interface; no VNI/mcast-address: " << uri; return; } std::shared_ptr vt_mc = EndPointGroupManager::mk_mcast_tunnel( m_runtime, uuid, bd_vnid.get(), maddr.get()); /* * there's no leanring of EPs in an external BD */ gbp_bridge_domain gbd( bd, *bvi, {}, vt_mc, gbp_bridge_domain::flags_t::DO_NOT_LEARN); OM::write(uuid, gbd); std::shared_ptr grd = EndPointGroupManager::mk_gbp_rd(m_runtime, uuid, rd, rd_vnid.get()); /* * the encap on the external-interface is a vlan ID */ boost::optional vlan_id = ext_itf.get()->getEncap(); if (vlan_id) ; /* * Add the /32 to the BVI */ boost::optional s_addr = ext_itf.get()->getAddress(); if (!s_addr) { VLOGI << "External-Interface; no prefix: " << uri; return; } boost::asio::ip::address p_addr = boost::asio::ip::address::from_string(s_addr.get()); l3_binding l3b(*bvi, {p_addr}); OM::write(uuid, l3b); bridge_domain_arp_entry bae(bd, p_addr, bvi->l2_address().to_mac()); OM::write(uuid, bae); opflexagent::PolicyManager::subnet_vector_t subnets; m_runtime.policy_manager().getSubnetsForExternalInterface(uri, subnets); for (auto sn : subnets) { if (!sn->getPrefixLen() || !sn->getAddress()) continue; route::prefix_t pfx(sn->getAddress().get(), sn->getPrefixLen().get()); route::ip_route ipr(rd, pfx, {route::path::special_t::DROP}); OM::write(uuid, ipr); } /* * This BVI is the ExternalInterface */ gbp_ext_itf gei(*bvi, gbd, *grd); OM::write(uuid, gei); /* * Add any external networks */ boost::optional> ext_dom = m_runtime.policy_manager().getExternalDomainForExternalInterface(uri); if (!ext_dom) { VLOGI << "External-Interface; no ExternalDomain: " << uri; return; } RouteManager::mk_ext_nets(m_runtime, rd, uri, ext_dom.get()); } }; // namepsace VPP /* * Local Variables: * eval: (c-set-style "llvm.org") * End: */