From 21a26f13b2e9088b5254173d8fb9a104367d5f6a Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sat, 18 Oct 2014 05:10:28 -0700 Subject: [PATCH 001/218] initial ovsdb change --- src/ksync/ksync_entry.h | 3 + src/ksync/ksync_object.cc | 3 + .../physical_devices/ovs_tor_agent/SConscript | 16 +- .../ovs_tor_agent/ovsdb_client/SConscript | 38 ++ .../ovsdb_client/logical_switch_ovsdb.cc | 240 ++++++++++ .../ovsdb_client/logical_switch_ovsdb.h | 66 +++ .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 27 ++ .../ovsdb_client/ovsdb_client.cc | 40 ++ .../ovs_tor_agent/ovsdb_client/ovsdb_client.h | 29 ++ .../ovsdb_client/ovsdb_client.sandesh | 21 + .../ovsdb_client/ovsdb_client_idl.cc | 144 ++++++ .../ovsdb_client/ovsdb_client_idl.h | 120 +++++ .../ovsdb_client/ovsdb_client_tcp.cc | 149 ++++++ .../ovsdb_client/ovsdb_client_tcp.h | 96 ++++ .../ovs_tor_agent/ovsdb_client/ovsdb_entry.cc | 150 ++++++ .../ovs_tor_agent/ovsdb_client/ovsdb_entry.h | 83 ++++ .../ovsdb_client/ovsdb_object.cc | 61 +++ .../ovs_tor_agent/ovsdb_client/ovsdb_object.h | 54 +++ .../ovsdb_client/ovsdb_wrapper.c | 436 ++++++++++++++++++ .../ovsdb_client/ovsdb_wrapper.h | 97 ++++ .../ovsdb_client/physical_locator_ovsdb.cc | 148 ++++++ .../ovsdb_client/physical_locator_ovsdb.h | 53 +++ .../ovsdb_client/physical_port_ovsdb.cc | 159 +++++++ .../ovsdb_client/physical_port_ovsdb.h | 48 ++ .../ovsdb_client/physical_switch_ovsdb.cc | 71 +++ .../ovsdb_client/physical_switch_ovsdb.h | 41 ++ .../ovsdb_client/unicast_mac_local_ovsdb.cc | 73 +++ .../ovsdb_client/unicast_mac_local_ovsdb.h | 40 ++ .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 148 ++++++ .../ovsdb_client/unicast_mac_remote_ovsdb.h | 56 +++ .../ovsdb_client/vlan_port_binding_ovsdb.cc | 135 ++++++ .../ovsdb_client/vlan_port_binding_ovsdb.h | 55 +++ .../ovs_tor_agent/tor_agent_init.cc | 5 + .../ovs_tor_agent/tor_agent_init.h | 5 + .../ovs_tor_agent/tor_agent_param.cc | 9 + .../ovs_tor_agent/tor_agent_param.h | 5 + 36 files changed, 2921 insertions(+), 3 deletions(-) create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h diff --git a/src/ksync/ksync_entry.h b/src/ksync/ksync_entry.h index 2ed6d3cc4a8..3ae49947254 100644 --- a/src/ksync/ksync_entry.h +++ b/src/ksync/ksync_entry.h @@ -99,6 +99,9 @@ class KSyncEntry { // Returns true if entry is resolved and referring entry can be written bool IsResolved(); + // Returns true if the entry data is resolved + virtual bool IsDataResolved() {return true;} + // User define KSync Response handler virtual void Response() { }; diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index 9bc1608e141..3064a037e7b 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -239,6 +239,8 @@ bool KSyncEntry::IsResolved() { KSyncObject *obj = GetObject(); if (obj->IsIndexValid() && index_ == kInvalidIndex) return false; + if (IsDataResolved() == false) + return false; return ((state_ >= IN_SYNC) && (state_ < DEL_DEFER_SYNC)); } @@ -945,6 +947,7 @@ void KSyncObject::NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event) { break; case KSyncEntry::SYNC_WAIT: + dep_reval = true; state = KSyncSM_SyncWait(this, entry, event); break; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript index 21ac69d6a80..3ebc6a1934c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript @@ -13,9 +13,18 @@ import subprocess Import('AgentEnv') env = AgentEnv.Clone() -env.Append(LIBPATH = [ '../tables' ]) -env.Prepend(LIBS = [ 'vnswinit' ]) -env.Append(LIBS = [ 'physical_devices' ]) +env.Append(LIBPATH = [ + '../tables', + 'ovsdb_client' + ]) +env.Prepend(LIBS = [ + 'ovsdbclient', + 'openvswitch', + 'vnswinit' + ]) +env.Append(LIBS = [ + 'physical_devices' + ]) env.GenerateBuildInfoCode( target='buildinfo.cc', @@ -36,6 +45,7 @@ tor_agent = env.Program(target = 'tor_agent', ]) env.Alias('agent:tor_agent', tor_agent) +env.SConscript('ovsdb_client/SConscript', exports='AgentEnv', duplicate=0) # Local Variables: # mode: python diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript new file mode 100644 index 00000000000..4af500b85fa --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -0,0 +1,38 @@ +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# + +# -*- mode: python; -*- + +Import('AgentEnv') + +env = AgentEnv.Clone() +env.CppEnableExceptions() + +env.Append(CPPPATH = './') +env.Append(CPPPATH = '#/build/include/openvswitch/include') +env.Append(CPPPATH = '#/build/include/openvswitch/lib') +env.Append(LIBPATH = '#/build/lib') +env.Append(LIBS = 'openvswitch') + +SandeshGenFiles = env.SandeshGenCpp('ovsdb.sandesh') +SandeshGenSrcs = env.ExtractCpp(SandeshGenFiles) +sandesh_objs = AgentEnv.BuildExceptionCppObj(env, SandeshGenSrcs) + +libovsdbclient = env.Library('ovsdbclient', + sandesh_objs + + [ + 'ovsdb_wrapper.c', + 'ovsdb_client.cc', + 'ovsdb_client_idl.cc', + 'ovsdb_client_tcp.cc', + 'ovsdb_entry.cc', + 'ovsdb_object.cc', + 'physical_switch_ovsdb.cc', + 'logical_switch_ovsdb.cc', + 'physical_port_ovsdb.cc', + 'vlan_port_binding_ovsdb.cc', + # 'physical_locator_ovsdb.cc', + # 'unicast_mac_local_ovsdb.cc', + ]) +env.Requires(libovsdbclient, '#/build/include/openvswitch/include') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc new file mode 100644 index 00000000000..f9f7fc89e33 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +#include +#include +#include + +using namespace AGENT; +using OVSDB::LogicalSwitchEntry; +using OVSDB::LogicalSwitchTable; +using OVSDB::OvsdbDBEntry; +using OVSDB::OvsdbDBObject; + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + const AGENT::PhysicalDeviceVnEntry *entry) : OvsdbDBEntry(table), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { + name_ = entry->vn()->GetName(); + vxlan_id_ = entry->vn()->GetVxLanId(); + device_name_ = entry->device()->name(); +} + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + const LogicalSwitchEntry *entry) : OvsdbDBEntry(table), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { + name_ = entry->name_; + vxlan_id_ = entry->vxlan_id_;; + device_name_ = entry->device_name_; +} + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), + name_(ovsdb_wrapper_logical_switch_name(entry)), device_name_(""), + vxlan_id_(ovsdb_wrapper_logical_switch_tunnel_key(entry)), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { +}; + +void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) { + struct ovsdb_idl_row *row = + ovsdb_wrapper_add_logical_switch(txn, ovs_entry_, name_.c_str(), + vxlan_id_); + /* Add remote multicast entry if not already present */ + if (mcast_remote_row_ == NULL) { + ovsdb_wrapper_add_mcast_mac_remote(txn, NULL, "unknown-dst", row, + table_->client_idl()->tsn_ip().to_string().c_str()); + } + if (old_mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); + } +} + +void LogicalSwitchEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void LogicalSwitchEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (mcast_local_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_local(mcast_local_row_); + } + if (mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(mcast_remote_row_); + } + if (old_mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); + } + ovsdb_wrapper_delete_logical_switch(ovs_entry_); +} + +void LogicalSwitchEntry::OvsdbChange() { + if (!IsResolved()) + table_->NotifyEvent(this, KSyncEntry::ADD_CHANGE_REQ); +} + +bool LogicalSwitchEntry::Sync(DBEntry *db_entry) { + PhysicalDeviceVnEntry *entry = + static_cast(db_entry); + if (vxlan_id_ != entry->vn()->GetVxLanId()) { + vxlan_id_ = entry->vn()->GetVxLanId(); + return true; + } + if (device_name_ != entry->device()->name()) { + device_name_ = entry->device()->name(); + return true; + } + return false; +} + +bool LogicalSwitchEntry::IsLess(const KSyncEntry &entry) const { + const LogicalSwitchEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *LogicalSwitchEntry::UnresolvedReference() { + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } + return NULL; +} + +LogicalSwitchTable::LogicalSwitchTable(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_LOGICAL_SWITCH, + boost::bind(&LogicalSwitchTable::OvsdbNotify, this, _1, _2)); + idl->Register(OvsdbClientIdl::OVSDB_MCAST_MAC_LOCAL, + boost::bind(&LogicalSwitchTable::OvsdbMcastLocalMacNotify, + this, _1, _2)); + idl->Register(OvsdbClientIdl::OVSDB_MCAST_MAC_REMOTE, + boost::bind(&LogicalSwitchTable::OvsdbMcastRemoteMacNotify, + this, _1, _2)); +} + +LogicalSwitchTable::~LogicalSwitchTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_LOGICAL_SWITCH); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_MCAST_MAC_LOCAL); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_MCAST_MAC_REMOTE); +} + +void LogicalSwitchTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Logical Switch %s, VxLAN %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + NotifyDeleteOvsdb((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Logical Switch %s, Vxlan %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + NotifyAddOvsdb((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +void LogicalSwitchTable::OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_mcast_mac_local_mac(row); + const char *ls = ovsdb_wrapper_mcast_mac_local_logical_switch(row); + LogicalSwitchEntry *entry; + if (ls) { + LogicalSwitchEntry key(this, ls); + entry = static_cast(Find(&key)); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of local mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = NULL; + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add of local mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = row; + } + } else { + assert(0); + } +} + +void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_mcast_mac_remote_mac(row); + const char *ls = ovsdb_wrapper_mcast_mac_remote_logical_switch(row); + LogicalSwitchEntry *entry = NULL; + if (ls) { + LogicalSwitchEntry key(this, ls); + entry = static_cast(Find(&key)); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of remote mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + if (entry->old_mcast_remote_row_ == row) + entry->old_mcast_remote_row_ = NULL; + if (entry->mcast_remote_row_ == row) + entry->mcast_remote_row_ = NULL; + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add of remote mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = row; + if (entry->mcast_remote_row_ != row) { + entry->old_mcast_remote_row_ = entry->mcast_remote_row_; + entry->mcast_remote_row_ = row; + entry->OvsdbChange(); + } + } + } else { + assert(0); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Logical Switch %s, VxLAN %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Logical Switch %s, Vxlan %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + } else { + assert(0); + } +} + +KSyncEntry *LogicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { + const LogicalSwitchEntry *k_entry = + static_cast(key); + LogicalSwitchEntry *entry = new LogicalSwitchEntry(this, k_entry); + return entry; +} + +KSyncEntry *LogicalSwitchTable::DBToKSyncEntry(const DBEntry* db_entry) { + const PhysicalDeviceVnEntry *entry = + static_cast(db_entry); + LogicalSwitchEntry *key = new LogicalSwitchEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *LogicalSwitchTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + LogicalSwitchEntry key(this, row); + return static_cast(Create(&key)); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h new file mode 100644 index 00000000000..3bb0709af08 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ + +#include +#include +#include + +namespace AGENT { +class PhysicalDeviceVnEntry; +}; + +namespace OVSDB { +class LogicalSwitchTable : public OvsdbDBObject { +public: + LogicalSwitchTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~LogicalSwitchTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + void OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + void OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + DISALLOW_COPY_AND_ASSIGN(LogicalSwitchTable); +}; + +class LogicalSwitchEntry : public OvsdbDBEntry { +public: + LogicalSwitchEntry(OvsdbDBObject *table, const char *name) : + OvsdbDBEntry(table), name_(name) {} + LogicalSwitchEntry(OvsdbDBObject *table, const LogicalSwitchEntry *key); + LogicalSwitchEntry(OvsdbDBObject *table, + const AGENT::PhysicalDeviceVnEntry *entry); + LogicalSwitchEntry(OvsdbDBObject *table, + struct ovsdb_idl_row *entry); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + + void OvsdbChange(); + + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Logical Switch";} + KSyncEntry* UnresolvedReference(); +private: + friend class LogicalSwitchTable; + std::string name_; + std::string device_name_; + int64_t vxlan_id_; + struct ovsdb_idl_row *mcast_local_row_; + struct ovsdb_idl_row *mcast_remote_row_; + struct ovsdb_idl_row *old_mcast_remote_row_; + DISALLOW_COPY_AND_ASSIGN(LogicalSwitchEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh new file mode 100644 index 00000000000..3f7f4efde8c --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +/**************************************************************************** + Sandesh definitions for OVSDB Client + ****************************************************************************/ + +struct SandeshOvsdbClientSession { + 1: string status; +} + +struct SandeshOvsdbClient { + 1: string protocol; + 2: string server; + 3: i16 port; + 4: string tor_service_node; + 5: list sessions; +} + +response sandesh OvsdbClientResp { + 1: SandeshOvsdbClient client; +} + +request sandesh OvsdbClientReq { +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc new file mode 100644 index 00000000000..5e02b189e4a --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +using OVSDB::OvsdbClient; + +void OvsdbClient::Init() { +} + +OvsdbClient *OvsdbClient::Allocate(Agent *agent, TorAgentParam *params) { + return (new OvsdbClientTcp(agent, params)); +} + +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +void OvsdbClientReq::HandleRequest() const { + OvsdbClientResp *resp = new OvsdbClientResp(); + SandeshOvsdbClient client_data; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClient *client = init->ovsdb_client(); + client_data.set_protocol(client->protocol()); + client_data.set_server(client->server()); + client_data.set_port(client->port()); + client_data.set_tor_service_node(client->tsn_ip().to_string()); + client->AddSessionInfo(client_data); + resp->set_client(client_data); + resp->set_context(context()); + resp->set_more(false); + resp->Response(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h new file mode 100644 index 00000000000..e51f171e63f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ + +class TorAgentParam; +class SandeshOvsdbClient; + +namespace OVSDB { +class OvsdbClient { +public: + OvsdbClient() {} + virtual ~OvsdbClient() {} + virtual void RegisterClients() = 0; + virtual const std::string protocol() = 0; + virtual const std::string server() = 0; + virtual uint16_t port() = 0; + virtual Ip4Address tsn_ip() = 0; + virtual void AddSessionInfo(SandeshOvsdbClient &client) = 0; + void Init(); + static OvsdbClient* Allocate(Agent *agent, TorAgentParam *params); +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbClient); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh new file mode 100644 index 00000000000..e49cd11f4fd --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +/**************************************************************************** + Sandesh definitions for OVSDB Client + ****************************************************************************/ + +struct OvsdbClientList { + 1: string protocol; + 2: string server; + 3: i16 port; + 4: list sessions (link=""); +} + +request sandesh OvsdbClientReq { +} + +request sandesh OvsdbClientSessionReq { +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc new file mode 100644 index 00000000000..7fb77b8d288 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +extern "C" { +#include +}; +#include +#include +#include +#include +#include +#if 0 +#include +#include +#endif + +#include + +namespace AGENT { +class PhysicalDeviceTable; +class PhysicalPortTable; +class LogicalPortTable; +class PhysicalDeviceVnTable; +} + +using OVSDB::OvsdbClientIdl; +using OVSDB::OvsdbClientSession; +using OVSDB::OvsdbEntryBase; + +namespace OVSDB { +void ovsdb_wrapper_idl_callback(void *idl_base, int op, + struct ovsdb_idl_row *row) { + OvsdbClientIdl *client_idl = (OvsdbClientIdl *) idl_base; + int i = ovsdb_wrapper_row_type(row); + if (i >= OvsdbClientIdl::OVSDB_TYPE_COUNT) + return; + if (client_idl->callback_[i] != NULL) + client_idl->callback_[i]((OvsdbClientIdl::Op)op, row); +} + +void ovsdb_wrapper_idl_txn_ack(void *idl_base, struct ovsdb_idl_txn *txn) { + OvsdbClientIdl *client_idl = (OvsdbClientIdl *) idl_base; + OvsdbEntryBase *entry = client_idl->pending_txn_[txn]; + bool success = ovsdb_wrapper_is_txn_success(txn); + client_idl->DeleteTxn(txn); + if (!success) { + printf("Transaction failed\n"); + } + if (entry) + entry->Ack(success); +} +}; + +OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent) : + idl_(ovsdb_wrapper_idl_create()), session_(session), pending_txn_() { + vtep_global_= ovsdb_wrapper_vteprec_global_first(idl_); + ovsdb_wrapper_idl_set_callback(idl_, (void *)this, + ovsdb_wrapper_idl_callback, ovsdb_wrapper_idl_txn_ack); + parser_ = NULL; + for (int i = 0; i < OVSDB_TYPE_COUNT; i++) { + callback_[i] = NULL; + } + physical_switch_table_.reset(new PhysicalSwitchTable(this)); + logical_switch_table_.reset(new LogicalSwitchTable(this, + (DBTable *)agent->device_manager()->physical_device_vn_table())); + physical_port_table_.reset(new PhysicalPortTable(this)); +#if 0 //TODO + physical_locator_table_.reset(new PhysicalLocatorTable(this, + (DBTable *)agent->nexthop_table())); + unicast_mac_local_table_.reset(new UnicastMacLocalTable(this)); +#endif +} + +OvsdbClientIdl::~OvsdbClientIdl() { + ovsdb_wrapper_idl_destroy(idl_); +} + +void OvsdbClientIdl::SendMointorReq() { + SendJsonRpc(ovsdb_wrapper_idl_encode_monitor_request(idl_)); +} + +void OvsdbClientIdl::SendJsonRpc(struct jsonrpc_msg *msg) { + struct json *json_msg = ovsdb_wrapper_jsonrpc_msg_to_json(msg); + char *s = ovsdb_wrapper_json_to_string(json_msg, 0); + ovsdb_wrapper_json_destroy(json_msg); + + session_->SendMsg((u_int8_t *)s, strlen(s)); +} + +void OvsdbClientIdl::MessageProcess(const u_int8_t *buf, std::size_t len) { + if (parser_ == NULL) { + parser_ = ovsdb_wrapper_json_parser_create(0); + } + ovsdb_wrapper_json_parser_feed(parser_, (const char *)buf, len); + + /* If we have complete JSON, attempt to parse it as JSON-RPC. */ + if (ovsdb_wrapper_json_parser_is_done(parser_)) { + struct json *json = ovsdb_wrapper_json_parser_finish(parser_); + parser_ = NULL; + struct jsonrpc_msg *msg; + char *error = ovsdb_wrapper_jsonrpc_msg_from_json(json, &msg); + if (error) { + free(error); + assert(0); + //return; + } + + if (ovsdb_wrapper_msg_echo_req(msg)) { + /* Echo request. Send reply. */ + struct jsonrpc_msg *reply; + reply = ovsdb_wrapper_jsonrpc_create_reply(msg); + SendJsonRpc(reply); + //jsonrpc_session_send(s, reply); + } else if (ovsdb_wrapper_msg_echo_reply(msg)) { + /* It's a reply to our echo request. Suppress it. */ + } else { + ovsdb_wrapper_idl_msg_process(idl_, msg); + return; + } + ovsdb_wrapper_jsonrpc_msg_destroy(msg); + } +} + +struct ovsdb_idl_txn *OvsdbClientIdl::CreateTxn(OvsdbEntryBase *entry) { + struct ovsdb_idl_txn *txn = ovsdb_wrapper_idl_txn_create(idl_); + pending_txn_[txn] = entry; + return txn; +} + +void OvsdbClientIdl::DeleteTxn(struct ovsdb_idl_txn *txn) { + pending_txn_.erase(txn); + ovsdb_wrapper_idl_txn_destroy(txn); +} + +Ip4Address OvsdbClientIdl::tsn_ip() { + return session_->tsn_ip(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h new file mode 100644 index 00000000000..ed6d5bf421f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ + +#include + +#include +#include +#include + + +namespace OVSDB { +class OvsdbClientSession; +class PhysicalSwitchTable; +class LogicalSwitchTable; +class PhysicalPortTable; +class VlanPortBindingTable; +class PhysicalLocatorTable; +class UnicastMacLocalTable; +class OvsdbEntryBase; + +class OvsdbClientIdl { +public: + enum Op { + OVSDB_DEL = 0, + OVSDB_ADD, + OVSDB_INVALID_OP + }; + + enum EntryType { + OVSDB_PHYSICAL_SWITCH = 0, + OVSDB_LOGICAL_SWITCH, + OVSDB_PHYSICAL_PORT, + OVSDB_PHYSICAL_LOCATOR, + OVSDB_UCAST_MAC_LOCAL, + OVSDB_UCAST_MAC_REMOTE, + OVSDB_PHYSICAL_LOCATOR_SET, + OVSDB_MCAST_MAC_LOCAL, + OVSDB_MCAST_MAC_REMOTE, + OVSDB_TYPE_COUNT + }; + typedef boost::function NotifyCB; + typedef std::map PendingTxnMap; + + OvsdbClientIdl(OvsdbClientSession *session, Agent *agent); + virtual ~OvsdbClientIdl(); + + // Send request to start monitoring OVSDB server + void SendMointorReq(); + // Send encode json rpc messgage to OVSDB server + void SendJsonRpc(struct jsonrpc_msg *msg); + // Process the recevied message and trigger update to ovsdb client + void MessageProcess(const u_int8_t *buf, std::size_t len); + // Create a OVSDB transaction to start encoding an update + struct ovsdb_idl_txn *CreateTxn(OvsdbEntryBase *entry); + // Delete the OVSDB transaction + void DeleteTxn(struct ovsdb_idl_txn *txn); + void Register(EntryType type, NotifyCB cb) {callback_[type] = cb;} + void UnRegister(EntryType type) {callback_[type] = NULL;} + // Get TOR Service Node IP + Ip4Address tsn_ip(); + + PhysicalSwitchTable *physical_switch_table() {return physical_switch_table_.get();} + LogicalSwitchTable *logical_switch_table() {return logical_switch_table_.get();} + PhysicalPortTable *physical_port_table() {return physical_port_table_.get();} +#if 0 //TODO + PhysicalLocatorTable *physical_locator_table() {return physical_locator_table_.get();} +#endif +private: + friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); + friend void ovsdb_wrapper_idl_txn_ack(void *, struct ovsdb_idl_txn *); + + struct ovsdb_idl *idl_; + struct json_parser * parser_; + const struct vteprec_global *vtep_global_; + OvsdbClientSession *session_; + NotifyCB callback_[OVSDB_TYPE_COUNT]; + PendingTxnMap pending_txn_; + std::auto_ptr physical_switch_table_; + std::auto_ptr logical_switch_table_; + std::auto_ptr physical_port_table_; + std::auto_ptr vlan_port_table_; +#if 0 //TODO + std::auto_ptr physical_locator_table_; + std::auto_ptr unicast_mac_local_table_; +#endif + DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl); +}; + +class OvsdbClientSession { +public: + OvsdbClientSession(Agent *agent) : client_idl_(this, agent), agent_(agent) {} + virtual ~OvsdbClientSession() {} + + virtual Ip4Address tsn_ip() = 0; + virtual void SendMsg(u_int8_t *buf, std::size_t len) = 0; + void MessageProcess(const u_int8_t *buf, std::size_t len) { + client_idl_.MessageProcess(buf, len); + } + + void OnEstablish() { + client_idl_.SendMointorReq(); + } + + void OnClose() { + assert(0); + } +private: + friend class OvsdbClientIdl; + OvsdbClientIdl client_idl_; + Agent *agent_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientSession); +}; +}; + +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc new file mode 100644 index 00000000000..75708982cbb --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include + +#include +#include +#include + +#include + +using OVSDB::OvsdbClientTcp; +using OVSDB::OvsdbClientTcpSession; +using OVSDB::OvsdbClientTcpSessionReader; + +OvsdbClientTcp::OvsdbClientTcp(Agent *agent, TorAgentParam *params) : + TcpServer(agent->event_manager()), agent_(agent), session_(NULL), + server_ep_(IpAddress(params->tor_ip()), params->tor_port()), + tsn_ip_(params->tsn_ip()) { +} + +OvsdbClientTcp::~OvsdbClientTcp() { +} + +void OvsdbClientTcp::RegisterClients() { + session_ = CreateSession(); + Connect(session_, server_ep_); +} + +TcpSession *OvsdbClientTcp::AllocSession(Socket *socket) { + TcpSession *session = new OvsdbClientTcpSession(agent_, this, socket); + session->set_observer(boost::bind(&OvsdbClientTcp::OnSessionEvent, + this, _1, _2)); + return session; +} + +void OvsdbClientTcp::OnSessionEvent(TcpSession *session, + TcpSession::Event event) { + OvsdbClientTcpSession *tcp = static_cast(session); + switch (event) { + case TcpSession::CONNECT_FAILED: + /* Failed to Connect, Try Again! */ + Connect(session_, server_ep_); + tcp->set_status("Reconnect"); + break; + case TcpSession::CLOSE: + /* TODO need to handle reconnects */ + tcp->OnClose(); + break; + case TcpSession::CONNECT_COMPLETE: + tcp->set_status("Established"); + tcp->OnEstablish(); + break; + default: + break; + } +} + +const std::string OvsdbClientTcp::protocol() { + return "TCP"; +} + +const std::string OvsdbClientTcp::server() { + return server_ep_.address().to_string(); +} + +uint16_t OvsdbClientTcp::port() { + return server_ep_.port(); +} + +Ip4Address OvsdbClientTcp::tsn_ip() { + return tsn_ip_; +} + +void OvsdbClientTcp::AddSessionInfo(SandeshOvsdbClient &client){ + SandeshOvsdbClientSession session; + std::vector session_list; + OvsdbClientTcpSession *tcp = static_cast(session_); + session.set_status(tcp->status()); + session_list.push_back(session); + client.set_sessions(session_list); +} + +OvsdbClientTcpSession::OvsdbClientTcpSession(Agent *agent, TcpServer *server, + Socket *sock, bool async_ready) : OvsdbClientSession(agent), + TcpSession(server, sock, async_ready), status_("Init") { + reader_ = new OvsdbClientTcpSessionReader(this, + boost::bind(&OvsdbClientTcpSession::RecvMsg, this, _1, _2)); + /* + * Process the received messages in a KSync workqueue task context, + * to assure only one thread is writting data to OVSDB client. + */ + receive_queue_ = new WorkQueue( + TaskScheduler::GetInstance()->GetTaskId("Agent::KSync"), -1, + boost::bind(&OvsdbClientTcpSession::ReceiveDequeue, this, _1)); +} + +OvsdbClientTcpSession::~OvsdbClientTcpSession() { + delete reader_; + receive_queue_->Shutdown(); + delete receive_queue_; +} + +void OvsdbClientTcpSession::OnRead(Buffer buffer) { + reader_->OnRead(buffer); +} + +void OvsdbClientTcpSession::SendMsg(u_int8_t *buf, std::size_t len) { + Send(buf, len, NULL); +} + +void OvsdbClientTcpSession::RecvMsg(const u_int8_t *buf, std::size_t len) { + queue_msg msg; + msg.buf = (u_int8_t *)malloc(len); + memcpy(msg.buf, buf, len); + msg.len = len; + receive_queue_->Enqueue(msg); +} + +bool OvsdbClientTcpSession::ReceiveDequeue(queue_msg msg) { + MessageProcess(msg.buf, msg.len); + free(msg.buf); + return true; +} + +Ip4Address OvsdbClientTcpSession::tsn_ip() { + OvsdbClientTcp *ovs_server = static_cast(server()); + return ovs_server->tsn_ip(); +} + +OvsdbClientTcpSessionReader::OvsdbClientTcpSessionReader( + TcpSession *session, ReceiveCallback callback) : + TcpMessageReader(session, callback) { +} + +OvsdbClientTcpSessionReader::~OvsdbClientTcpSessionReader() { +} + +int OvsdbClientTcpSessionReader::MsgLength(Buffer buffer, int offset) { + size_t size = TcpSession::BufferSize(buffer); + int remain = size - offset; + if (remain < GetHeaderLenSize()) { + return -1; + } + + return remain; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h new file mode 100644 index 00000000000..d4b7e931a92 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace OVSDB { +class OvsdbClientTcpSessionReader : public TcpMessageReader { +public: + OvsdbClientTcpSessionReader(TcpSession *session, ReceiveCallback callback); + virtual ~OvsdbClientTcpSessionReader(); + +protected: + virtual int MsgLength(Buffer buffer, int offset); + + virtual const int GetHeaderLenSize() { + // We don't have any header + return 0; + } + + virtual const int GetMaxMessageSize() { + return kMaxMessageSize; + } + +private: + static const int kMaxMessageSize = 4096; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcpSessionReader); +}; + +class OvsdbClientTcpSession : public OvsdbClientSession, public TcpSession { +public: + struct queue_msg { + u_int8_t *buf; + std::size_t len; + }; + OvsdbClientTcpSession(Agent *agent, TcpServer *server, Socket *sock, + bool async_ready = true); + ~OvsdbClientTcpSession(); + + // Send message to OVSDB server + void SendMsg(u_int8_t *buf, std::size_t len); + // Receive message from OVSDB server + void RecvMsg(const u_int8_t *buf, std::size_t len); + // Dequeue received message from workqueue for processing + bool ReceiveDequeue(queue_msg msg); + + Ip4Address tsn_ip(); + + void set_status(std::string status) {status_ = status;} + std::string status() {return status_;} + +protected: + virtual void OnRead(Buffer buffer); +private: + std::string status_; + OvsdbClientTcpSessionReader *reader_; + WorkQueue *receive_queue_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcpSession); +}; + +class OvsdbClientTcp : public TcpServer, public OvsdbClient { +public: + OvsdbClientTcp(Agent *agent, TorAgentParam *params); + virtual ~OvsdbClientTcp(); + + virtual TcpSession *AllocSession(Socket *socket); + void RegisterClients(); + void OnSessionEvent(TcpSession *session, TcpSession::Event event); + const std::string protocol(); + const std::string server(); + uint16_t port(); + Ip4Address tsn_ip(); + void AddSessionInfo(SandeshOvsdbClient &client); +private: + friend class OvsdbClientTcpSession; + Agent *agent_; + TcpSession *session_; + boost::asio::ip::tcp::endpoint server_ep_; + Ip4Address tsn_ip_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcp); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc new file mode 100644 index 00000000000..45061c37e47 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +extern "C" { +#include +} +#include +#include + +using OVSDB::OvsdbEntry; +using OVSDB::OvsdbDBEntry; +using OVSDB::OvsdbObject; +using OVSDB::OvsdbDBObject; + +OvsdbEntry::OvsdbEntry(OvsdbObject *table) : KSyncEntry(), table_(table) { +} + +OvsdbEntry::OvsdbEntry(OvsdbObject *table, uint32_t index) : KSyncEntry(index), + table_(table) { +} + +OvsdbEntry::~OvsdbEntry() { +} + +bool OvsdbEntry::Add() { + return true; +} + +bool OvsdbEntry::Change() { + return true; +} + +bool OvsdbEntry::Delete() { + return true; +} + +KSyncObject *OvsdbEntry::GetObject() { + return table_; +} + +void OvsdbEntry::Ack(bool success) { +} + +OvsdbDBEntry::OvsdbDBEntry(OvsdbDBObject *table) : KSyncDBEntry(), table_(table), + ovs_entry_(NULL) { +} + +OvsdbDBEntry::OvsdbDBEntry(OvsdbDBObject *table, struct ovsdb_idl_row *ovs_entry) : KSyncDBEntry(), + table_(table), ovs_entry_(ovs_entry) { +} + +OvsdbDBEntry::~OvsdbDBEntry() { +} + +bool OvsdbDBEntry::Add() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + AddMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::Change() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + ChangeMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::Delete() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + DeleteMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::IsDataResolved() { + return (ovs_entry_ == NULL) ? false : true; +} + +bool OvsdbDBEntry::IsDelAckWaiting() { + KSyncState state = GetState(); + return (state >= DEL_DEFER_DEL_ACK && state <= RENEW_WAIT); +} + +bool OvsdbDBEntry::IsAddChangeAckWaiting() { + KSyncState state = GetState(); + return (state == SYNC_WAIT || state == NEED_SYNC || + state == DEL_DEFER_SYNC); +} + +void OvsdbDBEntry::NotifyAdd(struct ovsdb_idl_row *row) { + ovs_entry_ = row; + OvsdbChange(); +} + +void OvsdbDBEntry::NotifyDelete() { + ovs_entry_ = NULL; +} + +KSyncObject *OvsdbDBEntry::GetObject() { + return table_; +} + +void OvsdbDBEntry::Ack(bool success) { + OvsdbDBObject *object = static_cast(GetObject()); + // TODO we are not retrying as of now, + // success = true; + if (success) { + if (IsDelAckWaiting()) + object->NotifyEvent(this, KSyncEntry::DEL_ACK); + else if (IsAddChangeAckWaiting()) + object->NotifyEvent(this, KSyncEntry::ADD_ACK); + else + delete this; + } else { + // On Failure try again + if (IsDelAckWaiting()) { + //Delete(); + printf("Delete Transaction failed for %s\n", ToString().c_str()); + object->NotifyEvent(this, KSyncEntry::DEL_ACK); + } else if (IsAddChangeAckWaiting()) { + printf("Add Transaction failed for %s\n", ToString().c_str()); + object->NotifyEvent(this, KSyncEntry::ADD_ACK); + //Add(); + } else { + printf("Ovsdb Delete Transaction failed for %s\n", ToString().c_str()); + object->OvsdbNotify(OvsdbClientIdl::OVSDB_ADD, ovs_entry_); + delete this; + //Delete(); + } + } +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h new file mode 100644 index 00000000000..fba0a523bc9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ + +#include + +#include +#include + +class KSyncObject; + +namespace OVSDB { +class OvsdbObject; +class OvsdbDBObject; + +class OvsdbEntryBase { +public: + virtual void Ack(bool success) = 0; +}; + +class OvsdbEntry : public KSyncEntry, public OvsdbEntryBase { +public: + OvsdbEntry(OvsdbObject *table); + OvsdbEntry(OvsdbObject *table, uint32_t index); + virtual ~OvsdbEntry(); + + bool Add(); + bool Change(); + bool Delete(); + + KSyncObject* GetObject(); + void Ack(bool success); +protected: + OvsdbObject *table_; + struct ovsdb_idl_row *ovs_entry_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbEntry); +}; + +class OvsdbDBEntry : public KSyncDBEntry, public OvsdbEntryBase { +public: + OvsdbDBEntry(OvsdbDBObject *table); + OvsdbDBEntry(OvsdbDBObject *table, struct ovsdb_idl_row *ovs_entry); + virtual ~OvsdbDBEntry(); + + // Encode add message for entry + virtual void AddMsg(struct ovsdb_idl_txn *) = 0; + // Encode change message for entry + virtual void ChangeMsg(struct ovsdb_idl_txn *) = 0; + // Encode delete message for entry + virtual void DeleteMsg(struct ovsdb_idl_txn *) = 0; + + virtual void OvsdbChange() {} + + virtual void NotifyAdd(struct ovsdb_idl_row *); + virtual void NotifyDelete(); + + bool Add(); + bool Change(); + bool Delete(); + + bool IsDataResolved(); + bool IsDelAckWaiting(); + bool IsAddChangeAckWaiting(); + + struct ovsdb_idl_row *ovs_entry() {return ovs_entry_;} + void clear_ovs_entry() {ovs_entry_ = NULL;} + + KSyncObject* GetObject(); + void Ack(bool success); +protected: + OvsdbDBObject *table_; + struct ovsdb_idl_row *ovs_entry_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbDBEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc new file mode 100644 index 00000000000..58dba512056 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +using OVSDB::OvsdbObject; +using OVSDB::OvsdbDBObject; +using OVSDB::OvsdbDBEntry; + +OvsdbObject::OvsdbObject(OvsdbClientIdl *idl) : KSyncObject(), + client_idl_(idl) { +} + +OvsdbObject::~OvsdbObject() { +} + +OvsdbDBObject::OvsdbDBObject(OvsdbClientIdl *idl) : KSyncDBObject(), + client_idl_(idl) { +} + +OvsdbDBObject::OvsdbDBObject(OvsdbClientIdl *idl, DBTableBase *tbl) : + KSyncDBObject(tbl), client_idl_(idl) { +} + +OvsdbDBObject::~OvsdbDBObject() { +} + +void OvsdbDBObject::NotifyAddOvsdb(OvsdbDBEntry *key, struct ovsdb_idl_row *row) { + OvsdbDBEntry *entry = static_cast(Find(key)); + if (entry) { + if (entry->IsAddChangeAckWaiting()) { + entry->NotifyAdd(row); + } + } else { + //TODO trigger delete of this entry + OvsdbDBEntry *del_entry = AllocOvsEntry(row); + Delete(del_entry); + //del_entry->Delete(); + //delete del_entry; + } +} + +void OvsdbDBObject::NotifyDeleteOvsdb(OvsdbDBEntry *key) { + OvsdbDBEntry *entry = static_cast(Find(key)); + if (entry) { + if (entry->IsDelAckWaiting()) { + entry->NotifyDelete(); + } else { + // Clear OVS State and trigger Add/Change Req on entry + entry->clear_ovs_entry(); + NotifyEvent(entry, KSyncEntry::ADD_CHANGE_REQ); + } + } +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h new file mode 100644 index 00000000000..755699ee47f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ + +#include + +#include +#include +#include +#include + +#include + +namespace OVSDB { +class OvsdbDBEntry; + +class OvsdbObject : public KSyncObject { +public: + OvsdbObject(OvsdbClientIdl *idl); + virtual ~OvsdbObject(); + + OvsdbClientIdl *client_idl() { return client_idl_;} +protected: + OvsdbClientIdl *client_idl_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbObject); +}; + +class OvsdbDBObject : public KSyncDBObject { +public: + OvsdbDBObject(OvsdbClientIdl *idl); + OvsdbDBObject(OvsdbClientIdl *idl, DBTableBase *tbl); + virtual ~OvsdbDBObject(); + + void NotifyAddOvsdb(OvsdbDBEntry *key, struct ovsdb_idl_row *row); + void NotifyDeleteOvsdb(OvsdbDBEntry *key); + + virtual void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *) = 0; + virtual OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row) = 0; + + OvsdbClientIdl *client_idl() { return client_idl_;} +protected: + OvsdbClientIdl *client_idl_; +private: + friend class OvsdbDBEntry; + DISALLOW_COPY_AND_ASSIGN(OvsdbDBObject); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c new file mode 100644 index 00000000000..780495d7085 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#define OPEN_CONTRAIL_CLIENT +#include +#include +#include +#include +#include + +#include + +void ovsdb_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + idl_callback cb, txn_ack_callback ack_cb); +struct jsonrpc_msg * ovsdb_idl_encode_monitor_request(struct ovsdb_idl *idl); +void ovsdb_idl_msg_process(struct ovsdb_idl *idl, struct jsonrpc_msg *msg); +struct jsonrpc_msg * ovsdb_idl_txn_encode(struct ovsdb_idl_txn *txn); + +struct ovsdb_idl * +ovsdb_wrapper_idl_create() +{ + vteprec_init(); + return ovsdb_idl_create(NULL, &vteprec_idl_class, true, false); +} + +void +ovsdb_wrapper_idl_destroy(struct ovsdb_idl *idl) +{ + ovsdb_idl_destroy(idl); +} + +const struct vteprec_global * +ovsdb_wrapper_vteprec_global_first(struct ovsdb_idl *idl) +{ + return vteprec_global_first(idl); +} + +int +ovsdb_wrapper_row_type(struct ovsdb_idl_row *row) { + if (row->table->class->columns == vteprec_physical_switch_columns) { + return 0; + } else if (row->table->class->columns == vteprec_logical_switch_columns) { + return 1; + } else if (row->table->class->columns == vteprec_physical_port_columns) { + return 2; + } else if (row->table->class->columns == vteprec_physical_locator_columns) { + return 3; + } else if (row->table->class->columns == vteprec_ucast_macs_local_columns) { + return 4; + } else if (row->table->class->columns == vteprec_ucast_macs_remote_columns) { + return 5; + } else if (row->table->class->columns == vteprec_physical_locator_set_columns) { + return 6; + } else if (row->table->class->columns == vteprec_mcast_macs_local_columns) { + return 7; + } else if (row->table->class->columns == vteprec_mcast_macs_remote_columns) { + return 8; + } + return 100; +} + +bool +ovsdb_wrapper_msg_echo_req(struct jsonrpc_msg *msg) { + return (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")); +} + +bool +ovsdb_wrapper_msg_echo_reply(struct jsonrpc_msg *msg) { + return (msg->type == JSONRPC_REPLY && msg->id && + msg->id->type == JSON_STRING && !strcmp(msg->id->u.string, "echo")); +} + +struct jsonrpc_msg * +ovsdb_wrapper_jsonrpc_create_reply(struct jsonrpc_msg *msg) { + return jsonrpc_create_reply(json_clone(msg->params), msg->id); +} + +void +ovsdb_wrapper_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + idl_callback cb, txn_ack_callback ack_cb) +{ + ovsdb_idl_set_callback(idl, idl_base, cb, ack_cb); +} + +struct jsonrpc_msg * +ovsdb_wrapper_idl_encode_monitor_request(struct ovsdb_idl *idl) +{ + return ovsdb_idl_encode_monitor_request(idl); +} + +void +ovsdb_wrapper_idl_msg_process(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) +{ + ovsdb_idl_msg_process(idl, msg); +} + +struct json * +ovsdb_wrapper_jsonrpc_msg_to_json(struct jsonrpc_msg *msg) +{ + return jsonrpc_msg_to_json(msg); +} + +char * +ovsdb_wrapper_json_to_string(const struct json *msg, int flag) +{ + return json_to_string(msg, flag); +} + +void +ovsdb_wrapper_json_destroy(struct json *msg) +{ + json_destroy(msg); +} + +struct json_parser * +ovsdb_wrapper_json_parser_create(int flag) +{ + return json_parser_create(flag); +} + +size_t +ovsdb_wrapper_json_parser_feed(struct json_parser *parser, const char *msg, + size_t len) +{ + return json_parser_feed(parser, msg, len); +} + +bool +ovsdb_wrapper_json_parser_is_done(const struct json_parser *parser) +{ + return json_parser_is_done(parser); +} + +struct json * +ovsdb_wrapper_json_parser_finish(struct json_parser *parser) +{ + return json_parser_finish(parser); +} + +char * +ovsdb_wrapper_jsonrpc_msg_from_json(struct json *msg, struct jsonrpc_msg **rpc) +{ + return jsonrpc_msg_from_json(msg, rpc); +} + +void +ovsdb_wrapper_jsonrpc_msg_destroy(struct jsonrpc_msg *msg) +{ + jsonrpc_msg_destroy(msg); +} + +struct ovsdb_idl_txn * +ovsdb_wrapper_idl_txn_create(struct ovsdb_idl *idl) +{ + return ovsdb_idl_txn_create(idl); +} + +void +ovsdb_wrapper_idl_txn_destroy(struct ovsdb_idl_txn *txn) +{ + ovsdb_idl_txn_destroy(txn); +} + +bool +ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn) +{ + return ovsdb_idl_is_txn_success(txn); +} + +struct jsonrpc_msg * +ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn) +{ + return ovsdb_idl_txn_encode(txn); +} + +/* physical switch */ +char * +ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_switch *ps = + row ? CONTAINER_OF(row, struct vteprec_physical_switch, header_) : NULL; + return ps->name; +} + +char * +ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_switch *ps = + row ? CONTAINER_OF(row, struct vteprec_physical_switch, header_) : NULL; + return ps->management_ips[0]; +} + +/* logical switch */ +char * +ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + return ls->name; +} + +int64_t +ovsdb_wrapper_logical_switch_tunnel_key(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + return *ls->tunnel_key; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_add_logical_switch(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *name, int64_t vxlan) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + if (ls == NULL) + ls = vteprec_logical_switch_insert(txn); + vteprec_logical_switch_set_name(ls, name); + vteprec_logical_switch_set_tunnel_key(ls, &vxlan, 1); + return &(ls->header_); +} + +void +ovsdb_wrapper_delete_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + CONTAINER_OF(row, struct vteprec_logical_switch, header_); + vteprec_logical_switch_delete(ls); +} + +/* physical port */ +char * +ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + return p->name; +} + +size_t +ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + return p->n_vlan_bindings; +} + +void +ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding *binding) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + size_t count = p->n_vlan_bindings; + size_t i = 0; + while (i < count) { + binding[i].vlan = p->key_vlan_bindings[i]; + binding[i].ls = ((struct ovsdb_idl_row *) ((char *)(p->value_vlan_bindings[i]) + offsetof(struct vteprec_logical_switch, header_))); + i++; + } +} + +void +ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding *bindings, size_t binding_count) +{ + struct vteprec_physical_port *p = + CONTAINER_OF(row, struct vteprec_physical_port, header_); + size_t i = 0; + int64_t binding_keys[binding_count]; + struct vteprec_logical_switch *binding_values[binding_count]; + while (i < binding_count) { + binding_keys[i] = bindings[i].vlan; + binding_values[i] = CONTAINER_OF(bindings[i].ls, struct vteprec_logical_switch, header_); + i++; + } + vteprec_physical_port_set_vlan_bindings(p, binding_keys, binding_values, + binding_count); +} + +/* physical locator */ +char * +ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + return p->dst_ip; +} + +void +ovsdb_wrapper_add_physical_locator(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *dip) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + if (p == NULL) + p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); +} + +void +ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + vteprec_physical_locator_delete(p); +} + +/* unicast mac local */ +char * +ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + return mac->MAC; +} + +char * +ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + return mac->ipaddr; +} + +char * +ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + if (mac->logical_switch) { + return mac->logical_switch->name; + } + return NULL; +} + +/* multicast mac local */ +void +ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + struct vteprec_physical_locator_set *l_set = mcast->locator_set; + vteprec_physical_locator_set_delete(l_set); + vteprec_mcast_macs_local_delete(mcast); +} + +char * +ovsdb_wrapper_mcast_mac_local_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + return mcast->MAC; +} + +char * +ovsdb_wrapper_mcast_mac_local_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + if (mcast->logical_switch) + return mcast->logical_switch->name; + return NULL; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + return &(mcast->locator_set->header_); +} + +/* multicast mac remote */ +void +ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, + const char *dst_ip) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + struct vteprec_physical_locator_set *l_set = + vteprec_physical_locator_set_insert(txn); + if (mcast == NULL) { + mcast = vteprec_mcast_macs_remote_insert(txn); + } + vteprec_mcast_macs_remote_set_MAC(mcast, mac); + vteprec_mcast_macs_remote_set_locator_set(mcast, l_set); + struct vteprec_logical_switch *l_switch = + ls ? CONTAINER_OF(ls, struct vteprec_logical_switch, header_) : NULL; + vteprec_mcast_macs_remote_set_logical_switch(mcast, l_switch); + struct vteprec_physical_locator *p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dst_ip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + vteprec_physical_locator_set_set_locators(l_set, &p, 1); +} + +void +ovsdb_wrapper_delete_mcast_mac_remote(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + struct vteprec_physical_locator_set *l_set = mcast->locator_set; + vteprec_physical_locator_set_delete(l_set); + vteprec_mcast_macs_remote_delete(mcast); +} + +char * +ovsdb_wrapper_mcast_mac_remote_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + return mcast->MAC; +} + +char * +ovsdb_wrapper_mcast_mac_remote_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + if (mcast->logical_switch) + return mcast->logical_switch->name; + return NULL; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + return &(mcast->locator_set->header_); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h new file mode 100644 index 00000000000..9823334c7d2 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ + +#include + +struct ovsdb_wrapper_port_vlan_binding { + int64_t vlan; + struct ovsdb_idl_row *ls; +}; + +/* Wrapper for C APIs */ +struct ovsdb_idl * ovsdb_wrapper_idl_create(); +void ovsdb_wrapper_idl_destroy(struct ovsdb_idl *idl); +const struct vteprec_global *ovsdb_wrapper_vteprec_global_first(struct ovsdb_idl *); +int ovsdb_wrapper_row_type(struct ovsdb_idl_row *row); +bool ovsdb_wrapper_msg_echo_req(struct jsonrpc_msg *msg); +bool ovsdb_wrapper_msg_echo_reply(struct jsonrpc_msg *msg); +struct jsonrpc_msg* ovsdb_wrapper_jsonrpc_create_reply(struct jsonrpc_msg *msg); + +void ovsdb_wrapper_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + void (*cb)(void*, int, struct ovsdb_idl_row *), + void (*ack_cb)(void*, struct ovsdb_idl_txn *)); +struct jsonrpc_msg *ovsdb_wrapper_idl_encode_monitor_request(struct ovsdb_idl *); +void ovsdb_wrapper_idl_msg_process(struct ovsdb_idl *, struct jsonrpc_msg *msg); +struct json *ovsdb_wrapper_jsonrpc_msg_to_json(struct jsonrpc_msg *); +char *ovsdb_wrapper_json_to_string(const struct json *, int); +void ovsdb_wrapper_json_destroy(struct json *); +struct json_parser *ovsdb_wrapper_json_parser_create(int); +size_t ovsdb_wrapper_json_parser_feed(struct json_parser *, const char *, size_t); +bool ovsdb_wrapper_json_parser_is_done(const struct json_parser *); +struct json *ovsdb_wrapper_json_parser_finish(struct json_parser *); +char *ovsdb_wrapper_jsonrpc_msg_from_json(struct json *, struct jsonrpc_msg **); +void ovsdb_wrapper_jsonrpc_msg_destroy(struct jsonrpc_msg *msg); + +struct ovsdb_idl_txn *ovsdb_wrapper_idl_txn_create(struct ovsdb_idl *idl); +void ovsdb_wrapper_idl_txn_destroy(struct ovsdb_idl_txn *txn); +bool ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn); +struct jsonrpc_msg *ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn); + +/* Physical Switch */ +char *ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row); + +/* Logical Switch */ +char *ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row); +int64_t ovsdb_wrapper_logical_switch_tunnel_key(struct ovsdb_idl_row *row); +struct ovsdb_idl_row *ovsdb_wrapper_add_logical_switch(struct ovsdb_idl_txn *, + struct ovsdb_idl_row *, const char *, int64_t); +void ovsdb_wrapper_delete_logical_switch(struct ovsdb_idl_row *); + +/* Physical Port */ +char *ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row); +size_t ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row); +void ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding*); +void ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *, struct ovsdb_idl_row *, + struct ovsdb_wrapper_port_vlan_binding*, size_t binding_count); + +/* Physical Locator */ +char *ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row); +void ovsdb_wrapper_add_physical_locator(struct ovsdb_idl_txn *, + struct ovsdb_idl_row *, const char *); +void ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *); + +/* unicast mac local */ +char *ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row); + +/* unicast mac remote */ + +/* multicast mac local */ +void ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_mcast_mac_local_mac(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_mcast_mac_local_logical_switch(struct ovsdb_idl_row *row); +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row); + +/* multicast mac remote */ +void ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, + const char *dst_ip); +void ovsdb_wrapper_delete_mcast_mac_remote(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_mcast_mac_remote_mac(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_mcast_mac_remote_logical_switch(struct ovsdb_idl_row *row); +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row); + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc new file mode 100644 index 00000000000..eca1a644559 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +#include +#include +#include +#include + +using namespace AGENT; + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), + is_vxlan_nh_(true), nh_(NULL) { +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const PhysicalLocatorEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), + is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const NextHop *entry) : OvsdbDBEntry(table), dip_(""), + is_vxlan_nh_(false), nh_(entry) { + if (entry->GetType() == NextHop::TUNNEL) { + const TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + dip_ = tunnel_nh->GetDip()->to_string(); + is_vxlan_nh_ = true; + } + } +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), + is_vxlan_nh_(true), nh_(NULL) { +} + +PhysicalLocatorEntry::~PhysicalLocatorEntry() { +} + +void PhysicalLocatorEntry::AddMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); +} + +void PhysicalLocatorEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void PhysicalLocatorEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_delete_physical_locator(ovs_entry_); +} + +bool PhysicalLocatorEntry::Sync(DBEntry *db_entry) { + NextHop *entry = static_cast(db_entry); + if (entry->GetType() == NextHop::TUNNEL) { + TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + if (dip_ != tunnel_nh->GetDip()->to_string()) { + // We don't handle dest ip change; + assert(0); + } + } + } + return false; +} + +bool PhysicalLocatorEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalLocatorEntry &pl_entry = + static_cast(entry); + if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { + return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); + } else if (!is_vxlan_nh_) { + return nh_ < pl_entry.nh_; + } + return (dip_ < pl_entry.dip_); +} + +KSyncEntry *PhysicalLocatorEntry::UnresolvedReference() { +#if 0 + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } +#endif + return NULL; +} + +PhysicalLocatorTable::PhysicalLocatorTable(OvsdbClientIdl *idl, + DBTable *table) : OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, + boost::bind(&PhysicalLocatorTable::OvsdbNotify, this, _1, _2)); +} + +PhysicalLocatorTable::~PhysicalLocatorTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR); +} + +void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + //NotifyDelete((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + //NotifyAdd((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +KSyncEntry *PhysicalLocatorTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalLocatorEntry *k_entry = + static_cast(key); + PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, k_entry); + return entry; +} + +KSyncEntry *PhysicalLocatorTable::DBToKSyncEntry(const DBEntry* db_entry) { + const NextHop *entry = + static_cast(db_entry); + PhysicalLocatorEntry *key = new PhysicalLocatorEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *PhysicalLocatorTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, row); + return static_cast(entry); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h new file mode 100644 index 00000000000..49485a8d419 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __PHYSICAL_LOCATOR_OVSDB_H__ +#define __PHYSICAL_LOCATOR_OVSDB_H__ + +#include + +class KSyncEntry; +class OvsdbDBEntry; +class PhysicalLocatorEntry; + +class PhysicalLocatorTable : public OvsdbDBObject { +public: + PhysicalLocatorTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~PhysicalLocatorTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + friend class PhysicalLocatorEntry; + DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorTable); +}; + +class PhysicalLocatorEntry : public OvsdbDBEntry { +public: + PhysicalLocatorEntry(PhysicalLocatorTable *table, const char *dip_str); + PhysicalLocatorEntry(PhysicalLocatorTable *table, + const PhysicalLocatorEntry *key); + PhysicalLocatorEntry(PhysicalLocatorTable *table, const NextHop *entry); + PhysicalLocatorEntry(PhysicalLocatorTable *table, struct ovsdb_idl_row *entry); + ~PhysicalLocatorEntry(); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Locator";} + KSyncEntry* UnresolvedReference(); +private: + friend class PhysicalLocatorTable; + std::string dip_; + bool is_vxlan_nh_; + const NextHop *nh_; + DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorEntry); +}; + +#endif //__PHYSICAL_LOCATOR_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc new file mode 100644 index 00000000000..70a25299bb9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +using OVSDB::PhysicalPortEntry; +using OVSDB::PhysicalPortTable; + +PhysicalPortEntry::PhysicalPortEntry(PhysicalPortTable *table, + const char *name) : OvsdbEntry(table), name_(name), binding_table_(), + ovs_binding_table_() { +} + +PhysicalPortEntry::PhysicalPortEntry(PhysicalPortTable *table, + const std::string &name) : OvsdbEntry(table), name_(name), + binding_table_(), ovs_binding_table_() { +} + +PhysicalPortEntry::~PhysicalPortEntry() { +} + +bool PhysicalPortEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalPortEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *PhysicalPortEntry::UnresolvedReference() { + return NULL; +} + +void PhysicalPortEntry::Encode(struct ovsdb_idl_txn *txn) { + if (GetState() == KSyncEntry::TEMP || IsDeleted()) { + /* + * we can only modify the vlan bindings in physical port + * table as we don't own the table, we are not suppose to create + * a new port entry in the table, so return from here if entry is + * marked temporary or deleted. + */ + return; + } + struct ovsdb_wrapper_port_vlan_binding binding[binding_table_.size()]; + VlanLSTable::iterator it = binding_table_.begin(); + std::size_t i = 0; + for ( ; it != binding_table_.end(); it++) { + struct ovsdb_idl_row *ls = it->second->ovs_entry(); + if (ls != NULL) { + binding[i].ls = ls; + binding[i].vlan = it->first; + i++; + } + } + ovsdb_wrapper_update_physical_port(txn, ovs_entry_, binding, i); +} + +void PhysicalPortEntry::AddBinding(int16_t vlan, LogicalSwitchEntry *ls) { +} + +void PhysicalPortEntry::DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls) { +} + +void PhysicalPortEntry::OverrideOvs() { + return; + //OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = table_->client_idl()->CreateTxn(this); + Encode(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + table_->client_idl()->DeleteTxn(txn); + return; + } + table_->client_idl()->SendJsonRpc(msg); +} + +PhysicalPortTable::PhysicalPortTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_PORT, + boost::bind(&PhysicalPortTable::Notify, this, _1, _2)); +} + +PhysicalPortTable::~PhysicalPortTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_PORT); +} + +void PhysicalPortTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + bool override_ovs = false; + PhysicalPortEntry *entry = NULL; + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Port %s\n", + ovsdb_wrapper_physical_port_name(row)); + PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Find(&key)); + if (entry != NULL) { + // TODO trigger notify delete for bindings + Delete(entry); + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Find(&key)); + if (entry == NULL) { + printf("Add/Change of Physical Port %s\n", + ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Create(&key)); + entry->ovs_entry_ = row; + } + PhysicalPortEntry::VlanLSTable old(entry->ovs_binding_table_); + std::size_t count = ovsdb_wrapper_physical_port_vlan_binding_count(row); + struct ovsdb_wrapper_port_vlan_binding new_bind[count]; + ovsdb_wrapper_physical_port_vlan_binding(row, new_bind); + for (std::size_t i = 0; i < count; i++) { + if (entry->binding_table_.find(new_bind[i].vlan) == + entry->binding_table_.end()) { + /* + * Entries present which are not owned by us, + * write port transaction to override the value. + */ + override_ovs = true; + continue; + } + LogicalSwitchEntry key(client_idl_->logical_switch_table(), + ovsdb_wrapper_logical_switch_name(new_bind[i].ls)); + LogicalSwitchEntry *ls_entry = + static_cast( + client_idl_->logical_switch_table()->Find(&key)); + entry->ovs_binding_table_[new_bind[i].vlan] = ls_entry; + old.erase(new_bind[i].vlan); + } + PhysicalPortEntry::VlanLSTable::iterator it = old.begin(); + for ( ; it != old.end(); it++) { + if (entry->binding_table_.find(it->first) != + entry->binding_table_.end()) { + /* + * Entry owned by us is somehow deleted, + * write port transaction to override the value. + */ + override_ovs = true; + } + entry->ovs_binding_table_.erase(it->first); + } + } else { + assert(0); + } + if (override_ovs) + entry->OverrideOvs(); +} + +KSyncEntry *PhysicalPortTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalPortEntry *k_entry = + static_cast(key); + PhysicalPortEntry *entry = new PhysicalPortEntry(this, k_entry->name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h new file mode 100644 index 00000000000..9c6837e3c89 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ + +#include +#include + +namespace OVSDB { +class PhysicalPortTable : public OvsdbObject { +public: + PhysicalPortTable(OvsdbClientIdl *idl); + virtual ~PhysicalPortTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(PhysicalPortTable); +}; + +class PhysicalPortEntry : public OvsdbEntry { +public: + typedef std::map VlanLSTable; + PhysicalPortEntry(PhysicalPortTable *table, const char *name); + PhysicalPortEntry(PhysicalPortTable *table, const std::string &name); + ~PhysicalPortEntry(); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Port";} + KSyncEntry* UnresolvedReference(); + void Encode(struct ovsdb_idl_txn *); + void AddBinding(int16_t vlan, LogicalSwitchEntry *ls); + void DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls); +private: + friend class PhysicalPortTable; + void OverrideOvs(); + std::string name_; + struct ovsdb_idl_row *ovs_entry_; + VlanLSTable binding_table_; + VlanLSTable ovs_binding_table_; + DISALLOW_COPY_AND_ASSIGN(PhysicalPortEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc new file mode 100644 index 00000000000..bb7f44a608b --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +using OVSDB::PhysicalSwitchEntry; +using OVSDB::PhysicalSwitchTable; + +PhysicalSwitchEntry::PhysicalSwitchEntry(PhysicalSwitchTable *table, + const std::string &name) : OvsdbEntry(table), name_(name) { +} + +PhysicalSwitchEntry::~PhysicalSwitchEntry() { +} + +bool PhysicalSwitchEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalSwitchEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *PhysicalSwitchEntry::UnresolvedReference() { + return NULL; +} + +PhysicalSwitchTable::PhysicalSwitchTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH, + boost::bind(&PhysicalSwitchTable::Notify, this, _1, _2)); +} + +PhysicalSwitchTable::~PhysicalSwitchTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH); +} + +void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Switch %s\n", + ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry *entry = + static_cast(Find(&key)); + if (entry != NULL) + Delete(entry); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Switch %s\n", + ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry *entry = + static_cast(Find(&key)); + if (entry == NULL) { + Create(&key); + } + } else { + assert(0); + } +} + +KSyncEntry *PhysicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalSwitchEntry *k_entry = + static_cast(key); + PhysicalSwitchEntry *entry = new PhysicalSwitchEntry(this, k_entry->name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h new file mode 100644 index 00000000000..50ecf5e7b71 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ + +#include +#include + +namespace OVSDB { +class PhysicalSwitchTable : public OvsdbObject { +public: + PhysicalSwitchTable(OvsdbClientIdl *idl); + virtual ~PhysicalSwitchTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchTable); +}; + +class PhysicalSwitchEntry : public OvsdbEntry { +public: + PhysicalSwitchEntry(PhysicalSwitchTable *table, const std::string &name); + ~PhysicalSwitchEntry(); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Switch";} + KSyncEntry* UnresolvedReference(); +private: + PhysicalSwitchEntry(PhysicalSwitchTable *table, const PhysicalSwitchEntry *key); + + friend class PhysicalSwitchTable; + std::string name_; + DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc new file mode 100644 index 00000000000..cee5ccc3fb9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include + +UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalTable *table, + struct ovsdb_idl_row *ovsdb_row, std::string mac, std::string ip_addr, + std::string ls_name) : OvsdbEntry(table), + ovsdb_row_(ovsdb_row), mac_(mac), ip_addr_(ip_addr), ls_name_(ls_name) { +} + +bool UnicastMacLocalEntry::IsLess(const KSyncEntry &entry) const { + const UnicastMacLocalEntry &uc_entry = + static_cast(entry); + return (ovsdb_row_ < uc_entry.ovsdb_row_); +} + +KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() { + return NULL; +} + +UnicastMacLocalTable::UnicastMacLocalTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, + boost::bind(&UnicastMacLocalTable::Notify, this, _1, _2)); +} + +UnicastMacLocalTable::~UnicastMacLocalTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL); +} + +void UnicastMacLocalTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + /* if logical switch is not avialable, trigger entry delete */ + bool delete_entry = + (ovsdb_wrapper_ucast_mac_local_logical_switch(row) == NULL); + const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row); + if (ls_name == NULL) + ls_name = ""; + UnicastMacLocalEntry key(this, row, ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + UnicastMacLocalEntry *entry = + static_cast(Find(&key)); + if (op == OvsdbClientIdl::OVSDB_DEL || delete_entry) { + printf("Delete of unicast local mac %s, IP %s, Logical Switch %s\n", + ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + if (entry != NULL) + Delete(entry); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of unicast local mac %s, IP %s, Logical Switch %s\n", + ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + if (entry == NULL) + Create(&key); + } else { + assert(0); + } +} + +KSyncEntry *UnicastMacLocalTable::Alloc(const KSyncEntry *key, uint32_t index) { + const UnicastMacLocalEntry *k_entry = + static_cast(key); + UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, + k_entry->ovsdb_row_, k_entry->mac_, k_entry->ip_addr_, + k_entry->ls_name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h new file mode 100644 index 00000000000..b281ecadc67 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __UNICAST_MAC_LOCAL_OVSDB_H__ +#define __UNICAST_MAC_LOCAL_OVSDB_H__ + +#include + +class UnicastMacLocalTable : public OvsdbObject { +public: + UnicastMacLocalTable(OvsdbClientIdl *idl); + virtual ~UnicastMacLocalTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalTable); +}; + +class UnicastMacLocalEntry : public OvsdbEntry { +public: + UnicastMacLocalEntry(UnicastMacLocalTable *table, + struct ovsdb_idl_row *ovsdb_row, std::string mac, + std::string ip_addr, std::string ls_name); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Unicast Mac Local";} + KSyncEntry* UnresolvedReference(); +private: + friend class UnicastMacLocalTable; + struct ovsdb_idl_row *ovsdb_row_; + std::string mac_; + std::string ip_addr_; + std::string ls_name_; + UnicastMacLocalTable *table_; +}; + +#endif //__UNICAST_MAC_LOCAL_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc new file mode 100644 index 00000000000..27db947ed66 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +#include +#include +#include +#include + +using namespace AGENT; + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), + is_vxlan_nh_(true), nh_(NULL) { +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const UnicastMacRemoteEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), + is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const NextHop *entry) : OvsdbDBEntry(table), dip_(""), + is_vxlan_nh_(false), nh_(entry) { + if (entry->GetType() == NextHop::TUNNEL) { + const TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + dip_ = tunnel_nh->GetDip()->to_string(); + is_vxlan_nh_ = true; + } + } +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), + is_vxlan_nh_(true), nh_(NULL) { +} + +UnicastMacRemoteEntry::~UnicastMacRemoteEntry() { +} + +void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); +} + +void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void UnicastMacRemoteEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_delete_physical_locator(ovs_entry_); +} + +bool UnicastMacRemoteEntry::Sync(DBEntry *db_entry) { + NextHop *entry = static_cast(db_entry); + if (entry->GetType() == NextHop::TUNNEL) { + TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + if (dip_ != tunnel_nh->GetDip()->to_string()) { + // We don't handle dest ip change; + assert(0); + } + } + } + return false; +} + +bool UnicastMacRemoteEntry::IsLess(const KSyncEntry &entry) const { + const UnicastMacRemoteEntry &pl_entry = + static_cast(entry); + if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { + return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); + } else if (!is_vxlan_nh_) { + return nh_ < pl_entry.nh_; + } + return (dip_ < pl_entry.dip_); +} + +KSyncEntry *UnicastMacRemoteEntry::UnresolvedReference() { +#if 0 + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } +#endif + return NULL; +} + +UnicastMacRemoteTable::UnicastMacRemoteTable(OvsdbClientIdl *idl, + DBTable *table) : OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, + boost::bind(&UnicastMacRemoteTable::OvsdbNotify, this, _1, _2)); +} + +UnicastMacRemoteTable::~UnicastMacRemoteTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR); +} + +void UnicastMacRemoteTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + NotifyDelete((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + NotifyAdd((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +KSyncEntry *UnicastMacRemoteTable::Alloc(const KSyncEntry *key, uint32_t index) { + const UnicastMacRemoteEntry *k_entry = + static_cast(key); + UnicastMacRemoteEntry *entry = new UnicastMacRemoteEntry(this, k_entry); + return entry; +} + +KSyncEntry *UnicastMacRemoteTable::DBToKSyncEntry(const DBEntry* db_entry) { + const NextHop *entry = + static_cast(db_entry); + UnicastMacRemoteEntry *key = new UnicastMacRemoteEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *UnicastMacRemoteTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + UnicastMacRemoteEntry *entry = new UnicastMacRemoteEntry(this, row); + return static_cast(entry); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h new file mode 100644 index 00000000000..94cee9c1662 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __UNICAST_MAC_REMOTE_OVSDB_H__ +#define __UNICAST_MAC_REMOTE_OVSDB_H__ + +#include + +class KSyncEntry; +class OvsdbDBEntry; +class UnicastMacRemoteEntry; + +class UnicastMacRemoteTable : public OvsdbDBObject { +public: + UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~UnicastMacRemoteTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + friend class UnicastMacRemoteEntry; + DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteTable); +}; + +class UnicastMacRemoteEntry : public OvsdbDBEntry { +public: + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + std::string l_switch_name, MacAddress mac_, std::string dest_ip); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const UnicastMacRemoteEntry *key); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, const NextHop *entry); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + struct ovsdb_idl_row *entry); + ~UnicastMacRemoteEntry(); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Unicast Remote Entry";} + KSyncEntry* UnresolvedReference(); +private: + friend class UnicastMacRemoteTable; + std::string l_switch_name_; + MacAddress mac_; + std::string dest_ip_; + + DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteEntry); +}; + +#endif //__UNICAST_MAC_REMOTE_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc new file mode 100644 index 00000000000..989642bb2b3 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using OVSDB::VlanPortBindingEntry; +using OVSDB::VlanPortBindingTable; +using OVSDB::PhysicalPortEntry; +using OVSDB::LogicalSwitchEntry; + +VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, + const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_) { + logical_switch_name_ = entry->vm_interface()->vn()->GetName(); + physical_port_name_ = entry->physical_port()->name(); + vlan_ = entry->vlan(); +} + +VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, + const VlanPortBindingEntry *key) : OvsdbDBEntry(table) { + logical_switch_name_ = key->logical_switch_name_; + physical_port_name_ = key->physical_port_name_; + vlan_ = key->vlan_; +} + +void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) { + PhysicalPortTable *p_table = table_->client_idl()->physical_port_table(); + PhysicalPortEntry key(p_table, physical_port_name_.c_str()); + physical_port_ = p_table->GetReference(&key); + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + logical_switch_ = l_table->GetReference(&ls_key); + + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->AddBinding(vlan_, + static_cast(logical_switch_.get())); + port->Encode(txn); +} + +void VlanPortBindingEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + if (physical_port_) { + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->DeleteBinding(vlan_, + static_cast(logical_switch_.get())); + physical_port_ = NULL; + logical_switch_ = NULL; + } + AddMsg(txn); +} + +void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!physical_port_) { + return; + } + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->DeleteBinding(vlan_, + static_cast(logical_switch_.get())); + physical_port_ = NULL; + logical_switch_ = NULL; + port->Encode(txn); +} + +bool VlanPortBindingEntry::Sync(DBEntry *db_entry) { + return false; +} + +bool VlanPortBindingEntry::IsLess(const KSyncEntry &entry) const { + const VlanPortBindingEntry &vps_entry = + static_cast(entry); + if (vlan_ != vps_entry.vlan_) + return vlan_ < vps_entry.vlan_; + if (physical_port_name_ != vps_entry.physical_port_name_) + return physical_port_name_ < vps_entry.physical_port_name_; + + return logical_switch_name_ < vps_entry.logical_switch_name_; +} + +KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { + PhysicalPortTable *p_table = table_->client_idl()->physical_port_table(); + PhysicalPortEntry key(p_table, physical_port_name_.c_str()); + PhysicalPortEntry *p_port = + static_cast(p_table->GetReference(&key)); + if (!p_port->IsResolved()) { + return p_port; + } + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *ls_entry = + static_cast(l_table->GetReference(&ls_key)); + if (!ls_entry->IsResolved()) { + return ls_entry; + } + return NULL; +} + +VlanPortBindingTable::VlanPortBindingTable(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { +} + +VlanPortBindingTable::~VlanPortBindingTable() { +} + +void VlanPortBindingTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { +} + +KSyncEntry *VlanPortBindingTable::Alloc(const KSyncEntry *key, uint32_t index) { + const VlanPortBindingEntry *k_entry = + static_cast(key); + VlanPortBindingEntry *entry = new VlanPortBindingEntry(this, k_entry); + return entry; +} + +KSyncEntry *VlanPortBindingTable::DBToKSyncEntry(const DBEntry* db_entry) { + const AGENT::VlanLogicalPortEntry *entry = + static_cast(db_entry); + VlanPortBindingEntry *key = new VlanPortBindingEntry(this, entry); + return static_cast(key); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h new file mode 100644 index 00000000000..851531ab705 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ + +#include +#include + +namespace AGENT { +class PhysicalDeviceVnEntry; +class VlanLogicalPortEntry; +}; + +namespace OVSDB { +class VlanPortBindingTable : public OvsdbDBObject { +public: + VlanPortBindingTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~VlanPortBindingTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row*); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); +private: + DISALLOW_COPY_AND_ASSIGN(VlanPortBindingTable); +}; + +class VlanPortBindingEntry : public OvsdbDBEntry { +public: + VlanPortBindingEntry(VlanPortBindingTable *table, + const VlanPortBindingEntry *key); + VlanPortBindingEntry(VlanPortBindingTable *table, + const AGENT::VlanLogicalPortEntry *entry); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Vlan Port Binding";} + KSyncEntry* UnresolvedReference(); +private: + friend class VlanPortBindingTable; + KSyncEntryPtr logical_switch_; + KSyncEntryPtr physical_port_; + std::string physical_port_name_; + std::string logical_switch_name_; + uint16_t vlan_; + DISALLOW_COPY_AND_ASSIGN(VlanPortBindingEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc index f9bb251d26a..feb5980f53f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc @@ -30,11 +30,13 @@ #include #include #include +#include #include using std::string; using std::cout; +using OVSDB::OvsdbClient; TorAgentInit::TorAgentInit() { } @@ -78,6 +80,8 @@ void TorAgentInit::CreatePeers() { void TorAgentInit::CreateModules() { device_manager_.reset(new PhysicalDeviceManager(agent())); agent()->set_device_manager(device_manager_.get()); + ovsdb_client_.reset(OvsdbClient::Allocate(agent(), + static_cast(agent_param()))); } void TorAgentInit::CreateDBTables() { @@ -86,6 +90,7 @@ void TorAgentInit::CreateDBTables() { void TorAgentInit::RegisterDBClients() { device_manager_->RegisterDBClients(); + ovsdb_client_->RegisterClients(); } void TorAgentInit::InitModules() { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h index f2b5da8a0b6..e107e8c70a9 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h @@ -14,6 +14,9 @@ class Agent; class AgentParam; class PhysicalDeviceManager; class OvsPeerManager; +namespace OVSDB { +class OvsdbClient; +}; // The class to drive agent initialization. // Defines control parameters used to enable/disable agent features @@ -44,10 +47,12 @@ class TorAgentInit : public AgentInit { // Accessor methods PhysicalDeviceManager *device_manager() const; OvsPeerManager *ovs_peer_manager() const; + OVSDB::OvsdbClient *ovsdb_client() {return ovsdb_client_.get();} private: std::auto_ptr device_manager_; std::auto_ptr ovs_peer_manager_; + std::auto_ptr ovsdb_client_; DISALLOW_COPY_AND_ASSIGN(TorAgentInit); }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc index 8492ccc13d6..58ae336c0bd 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc @@ -27,6 +27,8 @@ void TorAgentParam::AddOptions() { tor.add_options() ("TOR.tor_ip", boost_po::value()->default_value(""), "IP Address of the ToR being managed") + ("TOR.tsn_ip", boost_po::value()->default_value(""), + "IP Address of the ToR Service Node") ("TOR.tor_id", boost_po::value()->default_value(""), "Identifier of the TOR"); AgentParam::AddOptions(tor); @@ -39,6 +41,7 @@ void TorAgentParam::InitFromConfig() { // Parse ToR specific arguments ParseIp("TOR.tor_ip", &tor_info_.ip_); + ParseIp("TOR.tsn_ip", &tor_info_.tsn_ip_); GetValueFromTree(tor_info_.id_, "TOR.tor_id"); GetValueFromTree(tor_info_.type_, "TOR.tor_type"); GetValueFromTree(tor_info_.protocol_, "TOR.tor_ovs_protocol"); @@ -53,6 +56,7 @@ void TorAgentParam::InitFromArguments() { boost::program_options::variables_map vars = var_map(); ParseIpArgument(vars, tor_info_.ip_, "TOR.tor_ip"); + ParseIpArgument(vars, tor_info_.tsn_ip_, "TOR.tsn_ip"); GetOptValue(vars, tor_info_.id_, "TOR.tor_id"); GetOptValue(vars, tor_info_.type_, "TOR.tor_type"); GetOptValue(vars, tor_info_.protocol_, "TOR.tor_ovs_protocol"); @@ -65,6 +69,11 @@ int TorAgentParam::Validate() { return (EINVAL); } + if (tor_info_.tsn_ip_ == Ip4Address::from_string("0.0.0.0")) { + LOG(ERROR, "Configuration error. TSN IP address not specified"); + return (EINVAL); + } + if (tor_info_.id_ == "") { LOG(ERROR, "Configuration error. ToR ID not specified"); return (EINVAL); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h index abd9914e67b..9735abdee60 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h @@ -20,6 +20,7 @@ class TorAgentParam : public AgentParam { struct TorInfo { std::string type_; Ip4Address ip_; + Ip4Address tsn_ip_; std::string id_; // Protocol to connect to ToR std::string protocol_; @@ -33,6 +34,10 @@ class TorAgentParam : public AgentParam { void AddOptions(); std::string tor_id() const { return tor_info_.id_; } + std::string tor_protocol() const { return tor_info_.protocol_; } + Ip4Address tor_ip() const { return tor_info_.ip_; } + Ip4Address tsn_ip() const { return tor_info_.tsn_ip_; } + int tor_port() const { return tor_info_.port_; } private: virtual void InitFromConfig(); From 9c19b353f7339bfdf78deaa2b57acb1aa22220cd Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sat, 18 Oct 2014 05:10:28 -0700 Subject: [PATCH 002/218] initial ovsdb change --- src/ksync/ksync_entry.h | 3 + src/ksync/ksync_object.cc | 3 + .../physical_devices/ovs_tor_agent/SConscript | 16 +- .../ovs_tor_agent/ovsdb_client/SConscript | 38 ++ .../ovsdb_client/logical_switch_ovsdb.cc | 240 ++++++++++ .../ovsdb_client/logical_switch_ovsdb.h | 66 +++ .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 27 ++ .../ovsdb_client/ovsdb_client.cc | 40 ++ .../ovs_tor_agent/ovsdb_client/ovsdb_client.h | 29 ++ .../ovsdb_client/ovsdb_client.sandesh | 21 + .../ovsdb_client/ovsdb_client_idl.cc | 144 ++++++ .../ovsdb_client/ovsdb_client_idl.h | 120 +++++ .../ovsdb_client/ovsdb_client_tcp.cc | 149 ++++++ .../ovsdb_client/ovsdb_client_tcp.h | 96 ++++ .../ovs_tor_agent/ovsdb_client/ovsdb_entry.cc | 150 ++++++ .../ovs_tor_agent/ovsdb_client/ovsdb_entry.h | 83 ++++ .../ovsdb_client/ovsdb_object.cc | 61 +++ .../ovs_tor_agent/ovsdb_client/ovsdb_object.h | 54 +++ .../ovsdb_client/ovsdb_wrapper.c | 436 ++++++++++++++++++ .../ovsdb_client/ovsdb_wrapper.h | 97 ++++ .../ovsdb_client/physical_locator_ovsdb.cc | 148 ++++++ .../ovsdb_client/physical_locator_ovsdb.h | 53 +++ .../ovsdb_client/physical_port_ovsdb.cc | 159 +++++++ .../ovsdb_client/physical_port_ovsdb.h | 48 ++ .../ovsdb_client/physical_switch_ovsdb.cc | 71 +++ .../ovsdb_client/physical_switch_ovsdb.h | 41 ++ .../ovsdb_client/unicast_mac_local_ovsdb.cc | 73 +++ .../ovsdb_client/unicast_mac_local_ovsdb.h | 40 ++ .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 148 ++++++ .../ovsdb_client/unicast_mac_remote_ovsdb.h | 56 +++ .../ovsdb_client/vlan_port_binding_ovsdb.cc | 135 ++++++ .../ovsdb_client/vlan_port_binding_ovsdb.h | 55 +++ .../ovs_tor_agent/tor_agent_init.cc | 5 + .../ovs_tor_agent/tor_agent_init.h | 5 + .../ovs_tor_agent/tor_agent_param.cc | 9 + .../ovs_tor_agent/tor_agent_param.h | 5 + 36 files changed, 2921 insertions(+), 3 deletions(-) create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h diff --git a/src/ksync/ksync_entry.h b/src/ksync/ksync_entry.h index 2ed6d3cc4a8..3ae49947254 100644 --- a/src/ksync/ksync_entry.h +++ b/src/ksync/ksync_entry.h @@ -99,6 +99,9 @@ class KSyncEntry { // Returns true if entry is resolved and referring entry can be written bool IsResolved(); + // Returns true if the entry data is resolved + virtual bool IsDataResolved() {return true;} + // User define KSync Response handler virtual void Response() { }; diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index 9bc1608e141..3064a037e7b 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -239,6 +239,8 @@ bool KSyncEntry::IsResolved() { KSyncObject *obj = GetObject(); if (obj->IsIndexValid() && index_ == kInvalidIndex) return false; + if (IsDataResolved() == false) + return false; return ((state_ >= IN_SYNC) && (state_ < DEL_DEFER_SYNC)); } @@ -945,6 +947,7 @@ void KSyncObject::NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event) { break; case KSyncEntry::SYNC_WAIT: + dep_reval = true; state = KSyncSM_SyncWait(this, entry, event); break; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript index 21ac69d6a80..3ebc6a1934c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript @@ -13,9 +13,18 @@ import subprocess Import('AgentEnv') env = AgentEnv.Clone() -env.Append(LIBPATH = [ '../tables' ]) -env.Prepend(LIBS = [ 'vnswinit' ]) -env.Append(LIBS = [ 'physical_devices' ]) +env.Append(LIBPATH = [ + '../tables', + 'ovsdb_client' + ]) +env.Prepend(LIBS = [ + 'ovsdbclient', + 'openvswitch', + 'vnswinit' + ]) +env.Append(LIBS = [ + 'physical_devices' + ]) env.GenerateBuildInfoCode( target='buildinfo.cc', @@ -36,6 +45,7 @@ tor_agent = env.Program(target = 'tor_agent', ]) env.Alias('agent:tor_agent', tor_agent) +env.SConscript('ovsdb_client/SConscript', exports='AgentEnv', duplicate=0) # Local Variables: # mode: python diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript new file mode 100644 index 00000000000..4af500b85fa --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -0,0 +1,38 @@ +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# + +# -*- mode: python; -*- + +Import('AgentEnv') + +env = AgentEnv.Clone() +env.CppEnableExceptions() + +env.Append(CPPPATH = './') +env.Append(CPPPATH = '#/build/include/openvswitch/include') +env.Append(CPPPATH = '#/build/include/openvswitch/lib') +env.Append(LIBPATH = '#/build/lib') +env.Append(LIBS = 'openvswitch') + +SandeshGenFiles = env.SandeshGenCpp('ovsdb.sandesh') +SandeshGenSrcs = env.ExtractCpp(SandeshGenFiles) +sandesh_objs = AgentEnv.BuildExceptionCppObj(env, SandeshGenSrcs) + +libovsdbclient = env.Library('ovsdbclient', + sandesh_objs + + [ + 'ovsdb_wrapper.c', + 'ovsdb_client.cc', + 'ovsdb_client_idl.cc', + 'ovsdb_client_tcp.cc', + 'ovsdb_entry.cc', + 'ovsdb_object.cc', + 'physical_switch_ovsdb.cc', + 'logical_switch_ovsdb.cc', + 'physical_port_ovsdb.cc', + 'vlan_port_binding_ovsdb.cc', + # 'physical_locator_ovsdb.cc', + # 'unicast_mac_local_ovsdb.cc', + ]) +env.Requires(libovsdbclient, '#/build/include/openvswitch/include') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc new file mode 100644 index 00000000000..f9f7fc89e33 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +#include +#include +#include + +using namespace AGENT; +using OVSDB::LogicalSwitchEntry; +using OVSDB::LogicalSwitchTable; +using OVSDB::OvsdbDBEntry; +using OVSDB::OvsdbDBObject; + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + const AGENT::PhysicalDeviceVnEntry *entry) : OvsdbDBEntry(table), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { + name_ = entry->vn()->GetName(); + vxlan_id_ = entry->vn()->GetVxLanId(); + device_name_ = entry->device()->name(); +} + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + const LogicalSwitchEntry *entry) : OvsdbDBEntry(table), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { + name_ = entry->name_; + vxlan_id_ = entry->vxlan_id_;; + device_name_ = entry->device_name_; +} + +LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), + name_(ovsdb_wrapper_logical_switch_name(entry)), device_name_(""), + vxlan_id_(ovsdb_wrapper_logical_switch_tunnel_key(entry)), + mcast_local_row_(NULL), mcast_remote_row_(NULL), + old_mcast_remote_row_(NULL) { +}; + +void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) { + struct ovsdb_idl_row *row = + ovsdb_wrapper_add_logical_switch(txn, ovs_entry_, name_.c_str(), + vxlan_id_); + /* Add remote multicast entry if not already present */ + if (mcast_remote_row_ == NULL) { + ovsdb_wrapper_add_mcast_mac_remote(txn, NULL, "unknown-dst", row, + table_->client_idl()->tsn_ip().to_string().c_str()); + } + if (old_mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); + } +} + +void LogicalSwitchEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void LogicalSwitchEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (mcast_local_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_local(mcast_local_row_); + } + if (mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(mcast_remote_row_); + } + if (old_mcast_remote_row_ != NULL) { + ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); + } + ovsdb_wrapper_delete_logical_switch(ovs_entry_); +} + +void LogicalSwitchEntry::OvsdbChange() { + if (!IsResolved()) + table_->NotifyEvent(this, KSyncEntry::ADD_CHANGE_REQ); +} + +bool LogicalSwitchEntry::Sync(DBEntry *db_entry) { + PhysicalDeviceVnEntry *entry = + static_cast(db_entry); + if (vxlan_id_ != entry->vn()->GetVxLanId()) { + vxlan_id_ = entry->vn()->GetVxLanId(); + return true; + } + if (device_name_ != entry->device()->name()) { + device_name_ = entry->device()->name(); + return true; + } + return false; +} + +bool LogicalSwitchEntry::IsLess(const KSyncEntry &entry) const { + const LogicalSwitchEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *LogicalSwitchEntry::UnresolvedReference() { + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } + return NULL; +} + +LogicalSwitchTable::LogicalSwitchTable(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_LOGICAL_SWITCH, + boost::bind(&LogicalSwitchTable::OvsdbNotify, this, _1, _2)); + idl->Register(OvsdbClientIdl::OVSDB_MCAST_MAC_LOCAL, + boost::bind(&LogicalSwitchTable::OvsdbMcastLocalMacNotify, + this, _1, _2)); + idl->Register(OvsdbClientIdl::OVSDB_MCAST_MAC_REMOTE, + boost::bind(&LogicalSwitchTable::OvsdbMcastRemoteMacNotify, + this, _1, _2)); +} + +LogicalSwitchTable::~LogicalSwitchTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_LOGICAL_SWITCH); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_MCAST_MAC_LOCAL); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_MCAST_MAC_REMOTE); +} + +void LogicalSwitchTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Logical Switch %s, VxLAN %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + NotifyDeleteOvsdb((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Logical Switch %s, Vxlan %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + NotifyAddOvsdb((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +void LogicalSwitchTable::OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_mcast_mac_local_mac(row); + const char *ls = ovsdb_wrapper_mcast_mac_local_logical_switch(row); + LogicalSwitchEntry *entry; + if (ls) { + LogicalSwitchEntry key(this, ls); + entry = static_cast(Find(&key)); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of local mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = NULL; + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add of local mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = row; + } + } else { + assert(0); + } +} + +void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_mcast_mac_remote_mac(row); + const char *ls = ovsdb_wrapper_mcast_mac_remote_logical_switch(row); + LogicalSwitchEntry *entry = NULL; + if (ls) { + LogicalSwitchEntry key(this, ls); + entry = static_cast(Find(&key)); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of remote mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + if (entry->old_mcast_remote_row_ == row) + entry->old_mcast_remote_row_ = NULL; + if (entry->mcast_remote_row_ == row) + entry->mcast_remote_row_ = NULL; + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add of remote mcast mac %s, logical switch %s\n", + mac, ls ? ls : ""); + if (entry) { + entry->mcast_local_row_ = row; + if (entry->mcast_remote_row_ != row) { + entry->old_mcast_remote_row_ = entry->mcast_remote_row_; + entry->mcast_remote_row_ = row; + entry->OvsdbChange(); + } + } + } else { + assert(0); + } + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Logical Switch %s, VxLAN %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Logical Switch %s, Vxlan %ld\n", + ovsdb_wrapper_logical_switch_name(row), + ovsdb_wrapper_logical_switch_tunnel_key(row)); + } else { + assert(0); + } +} + +KSyncEntry *LogicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { + const LogicalSwitchEntry *k_entry = + static_cast(key); + LogicalSwitchEntry *entry = new LogicalSwitchEntry(this, k_entry); + return entry; +} + +KSyncEntry *LogicalSwitchTable::DBToKSyncEntry(const DBEntry* db_entry) { + const PhysicalDeviceVnEntry *entry = + static_cast(db_entry); + LogicalSwitchEntry *key = new LogicalSwitchEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *LogicalSwitchTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + LogicalSwitchEntry key(this, row); + return static_cast(Create(&key)); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h new file mode 100644 index 00000000000..3bb0709af08 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ + +#include +#include +#include + +namespace AGENT { +class PhysicalDeviceVnEntry; +}; + +namespace OVSDB { +class LogicalSwitchTable : public OvsdbDBObject { +public: + LogicalSwitchTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~LogicalSwitchTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + void OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + void OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + DISALLOW_COPY_AND_ASSIGN(LogicalSwitchTable); +}; + +class LogicalSwitchEntry : public OvsdbDBEntry { +public: + LogicalSwitchEntry(OvsdbDBObject *table, const char *name) : + OvsdbDBEntry(table), name_(name) {} + LogicalSwitchEntry(OvsdbDBObject *table, const LogicalSwitchEntry *key); + LogicalSwitchEntry(OvsdbDBObject *table, + const AGENT::PhysicalDeviceVnEntry *entry); + LogicalSwitchEntry(OvsdbDBObject *table, + struct ovsdb_idl_row *entry); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + + void OvsdbChange(); + + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Logical Switch";} + KSyncEntry* UnresolvedReference(); +private: + friend class LogicalSwitchTable; + std::string name_; + std::string device_name_; + int64_t vxlan_id_; + struct ovsdb_idl_row *mcast_local_row_; + struct ovsdb_idl_row *mcast_remote_row_; + struct ovsdb_idl_row *old_mcast_remote_row_; + DISALLOW_COPY_AND_ASSIGN(LogicalSwitchEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_LOGICAL_SWITCH_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh new file mode 100644 index 00000000000..3f7f4efde8c --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +/**************************************************************************** + Sandesh definitions for OVSDB Client + ****************************************************************************/ + +struct SandeshOvsdbClientSession { + 1: string status; +} + +struct SandeshOvsdbClient { + 1: string protocol; + 2: string server; + 3: i16 port; + 4: string tor_service_node; + 5: list sessions; +} + +response sandesh OvsdbClientResp { + 1: SandeshOvsdbClient client; +} + +request sandesh OvsdbClientReq { +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc new file mode 100644 index 00000000000..5e02b189e4a --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +using OVSDB::OvsdbClient; + +void OvsdbClient::Init() { +} + +OvsdbClient *OvsdbClient::Allocate(Agent *agent, TorAgentParam *params) { + return (new OvsdbClientTcp(agent, params)); +} + +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +void OvsdbClientReq::HandleRequest() const { + OvsdbClientResp *resp = new OvsdbClientResp(); + SandeshOvsdbClient client_data; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClient *client = init->ovsdb_client(); + client_data.set_protocol(client->protocol()); + client_data.set_server(client->server()); + client_data.set_port(client->port()); + client_data.set_tor_service_node(client->tsn_ip().to_string()); + client->AddSessionInfo(client_data); + resp->set_client(client_data); + resp->set_context(context()); + resp->set_more(false); + resp->Response(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h new file mode 100644 index 00000000000..e51f171e63f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ + +class TorAgentParam; +class SandeshOvsdbClient; + +namespace OVSDB { +class OvsdbClient { +public: + OvsdbClient() {} + virtual ~OvsdbClient() {} + virtual void RegisterClients() = 0; + virtual const std::string protocol() = 0; + virtual const std::string server() = 0; + virtual uint16_t port() = 0; + virtual Ip4Address tsn_ip() = 0; + virtual void AddSessionInfo(SandeshOvsdbClient &client) = 0; + void Init(); + static OvsdbClient* Allocate(Agent *agent, TorAgentParam *params); +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbClient); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh new file mode 100644 index 00000000000..e49cd11f4fd --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.sandesh @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +/**************************************************************************** + Sandesh definitions for OVSDB Client + ****************************************************************************/ + +struct OvsdbClientList { + 1: string protocol; + 2: string server; + 3: i16 port; + 4: list sessions (link=""); +} + +request sandesh OvsdbClientReq { +} + +request sandesh OvsdbClientSessionReq { +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc new file mode 100644 index 00000000000..7fb77b8d288 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +extern "C" { +#include +}; +#include +#include +#include +#include +#include +#if 0 +#include +#include +#endif + +#include + +namespace AGENT { +class PhysicalDeviceTable; +class PhysicalPortTable; +class LogicalPortTable; +class PhysicalDeviceVnTable; +} + +using OVSDB::OvsdbClientIdl; +using OVSDB::OvsdbClientSession; +using OVSDB::OvsdbEntryBase; + +namespace OVSDB { +void ovsdb_wrapper_idl_callback(void *idl_base, int op, + struct ovsdb_idl_row *row) { + OvsdbClientIdl *client_idl = (OvsdbClientIdl *) idl_base; + int i = ovsdb_wrapper_row_type(row); + if (i >= OvsdbClientIdl::OVSDB_TYPE_COUNT) + return; + if (client_idl->callback_[i] != NULL) + client_idl->callback_[i]((OvsdbClientIdl::Op)op, row); +} + +void ovsdb_wrapper_idl_txn_ack(void *idl_base, struct ovsdb_idl_txn *txn) { + OvsdbClientIdl *client_idl = (OvsdbClientIdl *) idl_base; + OvsdbEntryBase *entry = client_idl->pending_txn_[txn]; + bool success = ovsdb_wrapper_is_txn_success(txn); + client_idl->DeleteTxn(txn); + if (!success) { + printf("Transaction failed\n"); + } + if (entry) + entry->Ack(success); +} +}; + +OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent) : + idl_(ovsdb_wrapper_idl_create()), session_(session), pending_txn_() { + vtep_global_= ovsdb_wrapper_vteprec_global_first(idl_); + ovsdb_wrapper_idl_set_callback(idl_, (void *)this, + ovsdb_wrapper_idl_callback, ovsdb_wrapper_idl_txn_ack); + parser_ = NULL; + for (int i = 0; i < OVSDB_TYPE_COUNT; i++) { + callback_[i] = NULL; + } + physical_switch_table_.reset(new PhysicalSwitchTable(this)); + logical_switch_table_.reset(new LogicalSwitchTable(this, + (DBTable *)agent->device_manager()->physical_device_vn_table())); + physical_port_table_.reset(new PhysicalPortTable(this)); +#if 0 //TODO + physical_locator_table_.reset(new PhysicalLocatorTable(this, + (DBTable *)agent->nexthop_table())); + unicast_mac_local_table_.reset(new UnicastMacLocalTable(this)); +#endif +} + +OvsdbClientIdl::~OvsdbClientIdl() { + ovsdb_wrapper_idl_destroy(idl_); +} + +void OvsdbClientIdl::SendMointorReq() { + SendJsonRpc(ovsdb_wrapper_idl_encode_monitor_request(idl_)); +} + +void OvsdbClientIdl::SendJsonRpc(struct jsonrpc_msg *msg) { + struct json *json_msg = ovsdb_wrapper_jsonrpc_msg_to_json(msg); + char *s = ovsdb_wrapper_json_to_string(json_msg, 0); + ovsdb_wrapper_json_destroy(json_msg); + + session_->SendMsg((u_int8_t *)s, strlen(s)); +} + +void OvsdbClientIdl::MessageProcess(const u_int8_t *buf, std::size_t len) { + if (parser_ == NULL) { + parser_ = ovsdb_wrapper_json_parser_create(0); + } + ovsdb_wrapper_json_parser_feed(parser_, (const char *)buf, len); + + /* If we have complete JSON, attempt to parse it as JSON-RPC. */ + if (ovsdb_wrapper_json_parser_is_done(parser_)) { + struct json *json = ovsdb_wrapper_json_parser_finish(parser_); + parser_ = NULL; + struct jsonrpc_msg *msg; + char *error = ovsdb_wrapper_jsonrpc_msg_from_json(json, &msg); + if (error) { + free(error); + assert(0); + //return; + } + + if (ovsdb_wrapper_msg_echo_req(msg)) { + /* Echo request. Send reply. */ + struct jsonrpc_msg *reply; + reply = ovsdb_wrapper_jsonrpc_create_reply(msg); + SendJsonRpc(reply); + //jsonrpc_session_send(s, reply); + } else if (ovsdb_wrapper_msg_echo_reply(msg)) { + /* It's a reply to our echo request. Suppress it. */ + } else { + ovsdb_wrapper_idl_msg_process(idl_, msg); + return; + } + ovsdb_wrapper_jsonrpc_msg_destroy(msg); + } +} + +struct ovsdb_idl_txn *OvsdbClientIdl::CreateTxn(OvsdbEntryBase *entry) { + struct ovsdb_idl_txn *txn = ovsdb_wrapper_idl_txn_create(idl_); + pending_txn_[txn] = entry; + return txn; +} + +void OvsdbClientIdl::DeleteTxn(struct ovsdb_idl_txn *txn) { + pending_txn_.erase(txn); + ovsdb_wrapper_idl_txn_destroy(txn); +} + +Ip4Address OvsdbClientIdl::tsn_ip() { + return session_->tsn_ip(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h new file mode 100644 index 00000000000..ed6d5bf421f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ + +#include + +#include +#include +#include + + +namespace OVSDB { +class OvsdbClientSession; +class PhysicalSwitchTable; +class LogicalSwitchTable; +class PhysicalPortTable; +class VlanPortBindingTable; +class PhysicalLocatorTable; +class UnicastMacLocalTable; +class OvsdbEntryBase; + +class OvsdbClientIdl { +public: + enum Op { + OVSDB_DEL = 0, + OVSDB_ADD, + OVSDB_INVALID_OP + }; + + enum EntryType { + OVSDB_PHYSICAL_SWITCH = 0, + OVSDB_LOGICAL_SWITCH, + OVSDB_PHYSICAL_PORT, + OVSDB_PHYSICAL_LOCATOR, + OVSDB_UCAST_MAC_LOCAL, + OVSDB_UCAST_MAC_REMOTE, + OVSDB_PHYSICAL_LOCATOR_SET, + OVSDB_MCAST_MAC_LOCAL, + OVSDB_MCAST_MAC_REMOTE, + OVSDB_TYPE_COUNT + }; + typedef boost::function NotifyCB; + typedef std::map PendingTxnMap; + + OvsdbClientIdl(OvsdbClientSession *session, Agent *agent); + virtual ~OvsdbClientIdl(); + + // Send request to start monitoring OVSDB server + void SendMointorReq(); + // Send encode json rpc messgage to OVSDB server + void SendJsonRpc(struct jsonrpc_msg *msg); + // Process the recevied message and trigger update to ovsdb client + void MessageProcess(const u_int8_t *buf, std::size_t len); + // Create a OVSDB transaction to start encoding an update + struct ovsdb_idl_txn *CreateTxn(OvsdbEntryBase *entry); + // Delete the OVSDB transaction + void DeleteTxn(struct ovsdb_idl_txn *txn); + void Register(EntryType type, NotifyCB cb) {callback_[type] = cb;} + void UnRegister(EntryType type) {callback_[type] = NULL;} + // Get TOR Service Node IP + Ip4Address tsn_ip(); + + PhysicalSwitchTable *physical_switch_table() {return physical_switch_table_.get();} + LogicalSwitchTable *logical_switch_table() {return logical_switch_table_.get();} + PhysicalPortTable *physical_port_table() {return physical_port_table_.get();} +#if 0 //TODO + PhysicalLocatorTable *physical_locator_table() {return physical_locator_table_.get();} +#endif +private: + friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); + friend void ovsdb_wrapper_idl_txn_ack(void *, struct ovsdb_idl_txn *); + + struct ovsdb_idl *idl_; + struct json_parser * parser_; + const struct vteprec_global *vtep_global_; + OvsdbClientSession *session_; + NotifyCB callback_[OVSDB_TYPE_COUNT]; + PendingTxnMap pending_txn_; + std::auto_ptr physical_switch_table_; + std::auto_ptr logical_switch_table_; + std::auto_ptr physical_port_table_; + std::auto_ptr vlan_port_table_; +#if 0 //TODO + std::auto_ptr physical_locator_table_; + std::auto_ptr unicast_mac_local_table_; +#endif + DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl); +}; + +class OvsdbClientSession { +public: + OvsdbClientSession(Agent *agent) : client_idl_(this, agent), agent_(agent) {} + virtual ~OvsdbClientSession() {} + + virtual Ip4Address tsn_ip() = 0; + virtual void SendMsg(u_int8_t *buf, std::size_t len) = 0; + void MessageProcess(const u_int8_t *buf, std::size_t len) { + client_idl_.MessageProcess(buf, len); + } + + void OnEstablish() { + client_idl_.SendMointorReq(); + } + + void OnClose() { + assert(0); + } +private: + friend class OvsdbClientIdl; + OvsdbClientIdl client_idl_; + Agent *agent_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientSession); +}; +}; + +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc new file mode 100644 index 00000000000..75708982cbb --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include + +#include +#include +#include + +#include + +using OVSDB::OvsdbClientTcp; +using OVSDB::OvsdbClientTcpSession; +using OVSDB::OvsdbClientTcpSessionReader; + +OvsdbClientTcp::OvsdbClientTcp(Agent *agent, TorAgentParam *params) : + TcpServer(agent->event_manager()), agent_(agent), session_(NULL), + server_ep_(IpAddress(params->tor_ip()), params->tor_port()), + tsn_ip_(params->tsn_ip()) { +} + +OvsdbClientTcp::~OvsdbClientTcp() { +} + +void OvsdbClientTcp::RegisterClients() { + session_ = CreateSession(); + Connect(session_, server_ep_); +} + +TcpSession *OvsdbClientTcp::AllocSession(Socket *socket) { + TcpSession *session = new OvsdbClientTcpSession(agent_, this, socket); + session->set_observer(boost::bind(&OvsdbClientTcp::OnSessionEvent, + this, _1, _2)); + return session; +} + +void OvsdbClientTcp::OnSessionEvent(TcpSession *session, + TcpSession::Event event) { + OvsdbClientTcpSession *tcp = static_cast(session); + switch (event) { + case TcpSession::CONNECT_FAILED: + /* Failed to Connect, Try Again! */ + Connect(session_, server_ep_); + tcp->set_status("Reconnect"); + break; + case TcpSession::CLOSE: + /* TODO need to handle reconnects */ + tcp->OnClose(); + break; + case TcpSession::CONNECT_COMPLETE: + tcp->set_status("Established"); + tcp->OnEstablish(); + break; + default: + break; + } +} + +const std::string OvsdbClientTcp::protocol() { + return "TCP"; +} + +const std::string OvsdbClientTcp::server() { + return server_ep_.address().to_string(); +} + +uint16_t OvsdbClientTcp::port() { + return server_ep_.port(); +} + +Ip4Address OvsdbClientTcp::tsn_ip() { + return tsn_ip_; +} + +void OvsdbClientTcp::AddSessionInfo(SandeshOvsdbClient &client){ + SandeshOvsdbClientSession session; + std::vector session_list; + OvsdbClientTcpSession *tcp = static_cast(session_); + session.set_status(tcp->status()); + session_list.push_back(session); + client.set_sessions(session_list); +} + +OvsdbClientTcpSession::OvsdbClientTcpSession(Agent *agent, TcpServer *server, + Socket *sock, bool async_ready) : OvsdbClientSession(agent), + TcpSession(server, sock, async_ready), status_("Init") { + reader_ = new OvsdbClientTcpSessionReader(this, + boost::bind(&OvsdbClientTcpSession::RecvMsg, this, _1, _2)); + /* + * Process the received messages in a KSync workqueue task context, + * to assure only one thread is writting data to OVSDB client. + */ + receive_queue_ = new WorkQueue( + TaskScheduler::GetInstance()->GetTaskId("Agent::KSync"), -1, + boost::bind(&OvsdbClientTcpSession::ReceiveDequeue, this, _1)); +} + +OvsdbClientTcpSession::~OvsdbClientTcpSession() { + delete reader_; + receive_queue_->Shutdown(); + delete receive_queue_; +} + +void OvsdbClientTcpSession::OnRead(Buffer buffer) { + reader_->OnRead(buffer); +} + +void OvsdbClientTcpSession::SendMsg(u_int8_t *buf, std::size_t len) { + Send(buf, len, NULL); +} + +void OvsdbClientTcpSession::RecvMsg(const u_int8_t *buf, std::size_t len) { + queue_msg msg; + msg.buf = (u_int8_t *)malloc(len); + memcpy(msg.buf, buf, len); + msg.len = len; + receive_queue_->Enqueue(msg); +} + +bool OvsdbClientTcpSession::ReceiveDequeue(queue_msg msg) { + MessageProcess(msg.buf, msg.len); + free(msg.buf); + return true; +} + +Ip4Address OvsdbClientTcpSession::tsn_ip() { + OvsdbClientTcp *ovs_server = static_cast(server()); + return ovs_server->tsn_ip(); +} + +OvsdbClientTcpSessionReader::OvsdbClientTcpSessionReader( + TcpSession *session, ReceiveCallback callback) : + TcpMessageReader(session, callback) { +} + +OvsdbClientTcpSessionReader::~OvsdbClientTcpSessionReader() { +} + +int OvsdbClientTcpSessionReader::MsgLength(Buffer buffer, int offset) { + size_t size = TcpSession::BufferSize(buffer); + int remain = size - offset; + if (remain < GetHeaderLenSize()) { + return -1; + } + + return remain; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h new file mode 100644 index 00000000000..d4b7e931a92 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace OVSDB { +class OvsdbClientTcpSessionReader : public TcpMessageReader { +public: + OvsdbClientTcpSessionReader(TcpSession *session, ReceiveCallback callback); + virtual ~OvsdbClientTcpSessionReader(); + +protected: + virtual int MsgLength(Buffer buffer, int offset); + + virtual const int GetHeaderLenSize() { + // We don't have any header + return 0; + } + + virtual const int GetMaxMessageSize() { + return kMaxMessageSize; + } + +private: + static const int kMaxMessageSize = 4096; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcpSessionReader); +}; + +class OvsdbClientTcpSession : public OvsdbClientSession, public TcpSession { +public: + struct queue_msg { + u_int8_t *buf; + std::size_t len; + }; + OvsdbClientTcpSession(Agent *agent, TcpServer *server, Socket *sock, + bool async_ready = true); + ~OvsdbClientTcpSession(); + + // Send message to OVSDB server + void SendMsg(u_int8_t *buf, std::size_t len); + // Receive message from OVSDB server + void RecvMsg(const u_int8_t *buf, std::size_t len); + // Dequeue received message from workqueue for processing + bool ReceiveDequeue(queue_msg msg); + + Ip4Address tsn_ip(); + + void set_status(std::string status) {status_ = status;} + std::string status() {return status_;} + +protected: + virtual void OnRead(Buffer buffer); +private: + std::string status_; + OvsdbClientTcpSessionReader *reader_; + WorkQueue *receive_queue_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcpSession); +}; + +class OvsdbClientTcp : public TcpServer, public OvsdbClient { +public: + OvsdbClientTcp(Agent *agent, TorAgentParam *params); + virtual ~OvsdbClientTcp(); + + virtual TcpSession *AllocSession(Socket *socket); + void RegisterClients(); + void OnSessionEvent(TcpSession *session, TcpSession::Event event); + const std::string protocol(); + const std::string server(); + uint16_t port(); + Ip4Address tsn_ip(); + void AddSessionInfo(SandeshOvsdbClient &client); +private: + friend class OvsdbClientTcpSession; + Agent *agent_; + TcpSession *session_; + boost::asio::ip::tcp::endpoint server_ep_; + Ip4Address tsn_ip_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientTcp); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_TCP_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc new file mode 100644 index 00000000000..45061c37e47 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +extern "C" { +#include +} +#include +#include + +using OVSDB::OvsdbEntry; +using OVSDB::OvsdbDBEntry; +using OVSDB::OvsdbObject; +using OVSDB::OvsdbDBObject; + +OvsdbEntry::OvsdbEntry(OvsdbObject *table) : KSyncEntry(), table_(table) { +} + +OvsdbEntry::OvsdbEntry(OvsdbObject *table, uint32_t index) : KSyncEntry(index), + table_(table) { +} + +OvsdbEntry::~OvsdbEntry() { +} + +bool OvsdbEntry::Add() { + return true; +} + +bool OvsdbEntry::Change() { + return true; +} + +bool OvsdbEntry::Delete() { + return true; +} + +KSyncObject *OvsdbEntry::GetObject() { + return table_; +} + +void OvsdbEntry::Ack(bool success) { +} + +OvsdbDBEntry::OvsdbDBEntry(OvsdbDBObject *table) : KSyncDBEntry(), table_(table), + ovs_entry_(NULL) { +} + +OvsdbDBEntry::OvsdbDBEntry(OvsdbDBObject *table, struct ovsdb_idl_row *ovs_entry) : KSyncDBEntry(), + table_(table), ovs_entry_(ovs_entry) { +} + +OvsdbDBEntry::~OvsdbDBEntry() { +} + +bool OvsdbDBEntry::Add() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + AddMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::Change() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + ChangeMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::Delete() { + OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); + DeleteMsg(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + object->client_idl()->DeleteTxn(txn); + return true; + } + object->client_idl_->SendJsonRpc(msg); + return false; +} + +bool OvsdbDBEntry::IsDataResolved() { + return (ovs_entry_ == NULL) ? false : true; +} + +bool OvsdbDBEntry::IsDelAckWaiting() { + KSyncState state = GetState(); + return (state >= DEL_DEFER_DEL_ACK && state <= RENEW_WAIT); +} + +bool OvsdbDBEntry::IsAddChangeAckWaiting() { + KSyncState state = GetState(); + return (state == SYNC_WAIT || state == NEED_SYNC || + state == DEL_DEFER_SYNC); +} + +void OvsdbDBEntry::NotifyAdd(struct ovsdb_idl_row *row) { + ovs_entry_ = row; + OvsdbChange(); +} + +void OvsdbDBEntry::NotifyDelete() { + ovs_entry_ = NULL; +} + +KSyncObject *OvsdbDBEntry::GetObject() { + return table_; +} + +void OvsdbDBEntry::Ack(bool success) { + OvsdbDBObject *object = static_cast(GetObject()); + // TODO we are not retrying as of now, + // success = true; + if (success) { + if (IsDelAckWaiting()) + object->NotifyEvent(this, KSyncEntry::DEL_ACK); + else if (IsAddChangeAckWaiting()) + object->NotifyEvent(this, KSyncEntry::ADD_ACK); + else + delete this; + } else { + // On Failure try again + if (IsDelAckWaiting()) { + //Delete(); + printf("Delete Transaction failed for %s\n", ToString().c_str()); + object->NotifyEvent(this, KSyncEntry::DEL_ACK); + } else if (IsAddChangeAckWaiting()) { + printf("Add Transaction failed for %s\n", ToString().c_str()); + object->NotifyEvent(this, KSyncEntry::ADD_ACK); + //Add(); + } else { + printf("Ovsdb Delete Transaction failed for %s\n", ToString().c_str()); + object->OvsdbNotify(OvsdbClientIdl::OVSDB_ADD, ovs_entry_); + delete this; + //Delete(); + } + } +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h new file mode 100644 index 00000000000..fba0a523bc9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ + +#include + +#include +#include + +class KSyncObject; + +namespace OVSDB { +class OvsdbObject; +class OvsdbDBObject; + +class OvsdbEntryBase { +public: + virtual void Ack(bool success) = 0; +}; + +class OvsdbEntry : public KSyncEntry, public OvsdbEntryBase { +public: + OvsdbEntry(OvsdbObject *table); + OvsdbEntry(OvsdbObject *table, uint32_t index); + virtual ~OvsdbEntry(); + + bool Add(); + bool Change(); + bool Delete(); + + KSyncObject* GetObject(); + void Ack(bool success); +protected: + OvsdbObject *table_; + struct ovsdb_idl_row *ovs_entry_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbEntry); +}; + +class OvsdbDBEntry : public KSyncDBEntry, public OvsdbEntryBase { +public: + OvsdbDBEntry(OvsdbDBObject *table); + OvsdbDBEntry(OvsdbDBObject *table, struct ovsdb_idl_row *ovs_entry); + virtual ~OvsdbDBEntry(); + + // Encode add message for entry + virtual void AddMsg(struct ovsdb_idl_txn *) = 0; + // Encode change message for entry + virtual void ChangeMsg(struct ovsdb_idl_txn *) = 0; + // Encode delete message for entry + virtual void DeleteMsg(struct ovsdb_idl_txn *) = 0; + + virtual void OvsdbChange() {} + + virtual void NotifyAdd(struct ovsdb_idl_row *); + virtual void NotifyDelete(); + + bool Add(); + bool Change(); + bool Delete(); + + bool IsDataResolved(); + bool IsDelAckWaiting(); + bool IsAddChangeAckWaiting(); + + struct ovsdb_idl_row *ovs_entry() {return ovs_entry_;} + void clear_ovs_entry() {ovs_entry_ = NULL;} + + KSyncObject* GetObject(); + void Ack(bool success); +protected: + OvsdbDBObject *table_; + struct ovsdb_idl_row *ovs_entry_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbDBEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ENTRY_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc new file mode 100644 index 00000000000..58dba512056 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +using OVSDB::OvsdbObject; +using OVSDB::OvsdbDBObject; +using OVSDB::OvsdbDBEntry; + +OvsdbObject::OvsdbObject(OvsdbClientIdl *idl) : KSyncObject(), + client_idl_(idl) { +} + +OvsdbObject::~OvsdbObject() { +} + +OvsdbDBObject::OvsdbDBObject(OvsdbClientIdl *idl) : KSyncDBObject(), + client_idl_(idl) { +} + +OvsdbDBObject::OvsdbDBObject(OvsdbClientIdl *idl, DBTableBase *tbl) : + KSyncDBObject(tbl), client_idl_(idl) { +} + +OvsdbDBObject::~OvsdbDBObject() { +} + +void OvsdbDBObject::NotifyAddOvsdb(OvsdbDBEntry *key, struct ovsdb_idl_row *row) { + OvsdbDBEntry *entry = static_cast(Find(key)); + if (entry) { + if (entry->IsAddChangeAckWaiting()) { + entry->NotifyAdd(row); + } + } else { + //TODO trigger delete of this entry + OvsdbDBEntry *del_entry = AllocOvsEntry(row); + Delete(del_entry); + //del_entry->Delete(); + //delete del_entry; + } +} + +void OvsdbDBObject::NotifyDeleteOvsdb(OvsdbDBEntry *key) { + OvsdbDBEntry *entry = static_cast(Find(key)); + if (entry) { + if (entry->IsDelAckWaiting()) { + entry->NotifyDelete(); + } else { + // Clear OVS State and trigger Add/Change Req on entry + entry->clear_ovs_entry(); + NotifyEvent(entry, KSyncEntry::ADD_CHANGE_REQ); + } + } +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h new file mode 100644 index 00000000000..755699ee47f --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ + +#include + +#include +#include +#include +#include + +#include + +namespace OVSDB { +class OvsdbDBEntry; + +class OvsdbObject : public KSyncObject { +public: + OvsdbObject(OvsdbClientIdl *idl); + virtual ~OvsdbObject(); + + OvsdbClientIdl *client_idl() { return client_idl_;} +protected: + OvsdbClientIdl *client_idl_; +private: + DISALLOW_COPY_AND_ASSIGN(OvsdbObject); +}; + +class OvsdbDBObject : public KSyncDBObject { +public: + OvsdbDBObject(OvsdbClientIdl *idl); + OvsdbDBObject(OvsdbClientIdl *idl, DBTableBase *tbl); + virtual ~OvsdbDBObject(); + + void NotifyAddOvsdb(OvsdbDBEntry *key, struct ovsdb_idl_row *row); + void NotifyDeleteOvsdb(OvsdbDBEntry *key); + + virtual void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *) = 0; + virtual OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row) = 0; + + OvsdbClientIdl *client_idl() { return client_idl_;} +protected: + OvsdbClientIdl *client_idl_; +private: + friend class OvsdbDBEntry; + DISALLOW_COPY_AND_ASSIGN(OvsdbDBObject); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_OBJECT_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c new file mode 100644 index 00000000000..780495d7085 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#define OPEN_CONTRAIL_CLIENT +#include +#include +#include +#include +#include + +#include + +void ovsdb_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + idl_callback cb, txn_ack_callback ack_cb); +struct jsonrpc_msg * ovsdb_idl_encode_monitor_request(struct ovsdb_idl *idl); +void ovsdb_idl_msg_process(struct ovsdb_idl *idl, struct jsonrpc_msg *msg); +struct jsonrpc_msg * ovsdb_idl_txn_encode(struct ovsdb_idl_txn *txn); + +struct ovsdb_idl * +ovsdb_wrapper_idl_create() +{ + vteprec_init(); + return ovsdb_idl_create(NULL, &vteprec_idl_class, true, false); +} + +void +ovsdb_wrapper_idl_destroy(struct ovsdb_idl *idl) +{ + ovsdb_idl_destroy(idl); +} + +const struct vteprec_global * +ovsdb_wrapper_vteprec_global_first(struct ovsdb_idl *idl) +{ + return vteprec_global_first(idl); +} + +int +ovsdb_wrapper_row_type(struct ovsdb_idl_row *row) { + if (row->table->class->columns == vteprec_physical_switch_columns) { + return 0; + } else if (row->table->class->columns == vteprec_logical_switch_columns) { + return 1; + } else if (row->table->class->columns == vteprec_physical_port_columns) { + return 2; + } else if (row->table->class->columns == vteprec_physical_locator_columns) { + return 3; + } else if (row->table->class->columns == vteprec_ucast_macs_local_columns) { + return 4; + } else if (row->table->class->columns == vteprec_ucast_macs_remote_columns) { + return 5; + } else if (row->table->class->columns == vteprec_physical_locator_set_columns) { + return 6; + } else if (row->table->class->columns == vteprec_mcast_macs_local_columns) { + return 7; + } else if (row->table->class->columns == vteprec_mcast_macs_remote_columns) { + return 8; + } + return 100; +} + +bool +ovsdb_wrapper_msg_echo_req(struct jsonrpc_msg *msg) { + return (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")); +} + +bool +ovsdb_wrapper_msg_echo_reply(struct jsonrpc_msg *msg) { + return (msg->type == JSONRPC_REPLY && msg->id && + msg->id->type == JSON_STRING && !strcmp(msg->id->u.string, "echo")); +} + +struct jsonrpc_msg * +ovsdb_wrapper_jsonrpc_create_reply(struct jsonrpc_msg *msg) { + return jsonrpc_create_reply(json_clone(msg->params), msg->id); +} + +void +ovsdb_wrapper_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + idl_callback cb, txn_ack_callback ack_cb) +{ + ovsdb_idl_set_callback(idl, idl_base, cb, ack_cb); +} + +struct jsonrpc_msg * +ovsdb_wrapper_idl_encode_monitor_request(struct ovsdb_idl *idl) +{ + return ovsdb_idl_encode_monitor_request(idl); +} + +void +ovsdb_wrapper_idl_msg_process(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) +{ + ovsdb_idl_msg_process(idl, msg); +} + +struct json * +ovsdb_wrapper_jsonrpc_msg_to_json(struct jsonrpc_msg *msg) +{ + return jsonrpc_msg_to_json(msg); +} + +char * +ovsdb_wrapper_json_to_string(const struct json *msg, int flag) +{ + return json_to_string(msg, flag); +} + +void +ovsdb_wrapper_json_destroy(struct json *msg) +{ + json_destroy(msg); +} + +struct json_parser * +ovsdb_wrapper_json_parser_create(int flag) +{ + return json_parser_create(flag); +} + +size_t +ovsdb_wrapper_json_parser_feed(struct json_parser *parser, const char *msg, + size_t len) +{ + return json_parser_feed(parser, msg, len); +} + +bool +ovsdb_wrapper_json_parser_is_done(const struct json_parser *parser) +{ + return json_parser_is_done(parser); +} + +struct json * +ovsdb_wrapper_json_parser_finish(struct json_parser *parser) +{ + return json_parser_finish(parser); +} + +char * +ovsdb_wrapper_jsonrpc_msg_from_json(struct json *msg, struct jsonrpc_msg **rpc) +{ + return jsonrpc_msg_from_json(msg, rpc); +} + +void +ovsdb_wrapper_jsonrpc_msg_destroy(struct jsonrpc_msg *msg) +{ + jsonrpc_msg_destroy(msg); +} + +struct ovsdb_idl_txn * +ovsdb_wrapper_idl_txn_create(struct ovsdb_idl *idl) +{ + return ovsdb_idl_txn_create(idl); +} + +void +ovsdb_wrapper_idl_txn_destroy(struct ovsdb_idl_txn *txn) +{ + ovsdb_idl_txn_destroy(txn); +} + +bool +ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn) +{ + return ovsdb_idl_is_txn_success(txn); +} + +struct jsonrpc_msg * +ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn) +{ + return ovsdb_idl_txn_encode(txn); +} + +/* physical switch */ +char * +ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_switch *ps = + row ? CONTAINER_OF(row, struct vteprec_physical_switch, header_) : NULL; + return ps->name; +} + +char * +ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_switch *ps = + row ? CONTAINER_OF(row, struct vteprec_physical_switch, header_) : NULL; + return ps->management_ips[0]; +} + +/* logical switch */ +char * +ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + return ls->name; +} + +int64_t +ovsdb_wrapper_logical_switch_tunnel_key(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + return *ls->tunnel_key; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_add_logical_switch(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *name, int64_t vxlan) +{ + struct vteprec_logical_switch *ls = + row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; + if (ls == NULL) + ls = vteprec_logical_switch_insert(txn); + vteprec_logical_switch_set_name(ls, name); + vteprec_logical_switch_set_tunnel_key(ls, &vxlan, 1); + return &(ls->header_); +} + +void +ovsdb_wrapper_delete_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_logical_switch *ls = + CONTAINER_OF(row, struct vteprec_logical_switch, header_); + vteprec_logical_switch_delete(ls); +} + +/* physical port */ +char * +ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + return p->name; +} + +size_t +ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + return p->n_vlan_bindings; +} + +void +ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding *binding) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + size_t count = p->n_vlan_bindings; + size_t i = 0; + while (i < count) { + binding[i].vlan = p->key_vlan_bindings[i]; + binding[i].ls = ((struct ovsdb_idl_row *) ((char *)(p->value_vlan_bindings[i]) + offsetof(struct vteprec_logical_switch, header_))); + i++; + } +} + +void +ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding *bindings, size_t binding_count) +{ + struct vteprec_physical_port *p = + CONTAINER_OF(row, struct vteprec_physical_port, header_); + size_t i = 0; + int64_t binding_keys[binding_count]; + struct vteprec_logical_switch *binding_values[binding_count]; + while (i < binding_count) { + binding_keys[i] = bindings[i].vlan; + binding_values[i] = CONTAINER_OF(bindings[i].ls, struct vteprec_logical_switch, header_); + i++; + } + vteprec_physical_port_set_vlan_bindings(p, binding_keys, binding_values, + binding_count); +} + +/* physical locator */ +char * +ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + return p->dst_ip; +} + +void +ovsdb_wrapper_add_physical_locator(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *dip) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + if (p == NULL) + p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); +} + +void +ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_locator *p = + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + vteprec_physical_locator_delete(p); +} + +/* unicast mac local */ +char * +ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + return mac->MAC; +} + +char * +ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + return mac->ipaddr; +} + +char * +ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + if (mac->logical_switch) { + return mac->logical_switch->name; + } + return NULL; +} + +/* multicast mac local */ +void +ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + struct vteprec_physical_locator_set *l_set = mcast->locator_set; + vteprec_physical_locator_set_delete(l_set); + vteprec_mcast_macs_local_delete(mcast); +} + +char * +ovsdb_wrapper_mcast_mac_local_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + return mcast->MAC; +} + +char * +ovsdb_wrapper_mcast_mac_local_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + if (mcast->logical_switch) + return mcast->logical_switch->name; + return NULL; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_local *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_local, header_) : NULL; + return &(mcast->locator_set->header_); +} + +/* multicast mac remote */ +void +ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, + const char *dst_ip) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + struct vteprec_physical_locator_set *l_set = + vteprec_physical_locator_set_insert(txn); + if (mcast == NULL) { + mcast = vteprec_mcast_macs_remote_insert(txn); + } + vteprec_mcast_macs_remote_set_MAC(mcast, mac); + vteprec_mcast_macs_remote_set_locator_set(mcast, l_set); + struct vteprec_logical_switch *l_switch = + ls ? CONTAINER_OF(ls, struct vteprec_logical_switch, header_) : NULL; + vteprec_mcast_macs_remote_set_logical_switch(mcast, l_switch); + struct vteprec_physical_locator *p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dst_ip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + vteprec_physical_locator_set_set_locators(l_set, &p, 1); +} + +void +ovsdb_wrapper_delete_mcast_mac_remote(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + struct vteprec_physical_locator_set *l_set = mcast->locator_set; + vteprec_physical_locator_set_delete(l_set); + vteprec_mcast_macs_remote_delete(mcast); +} + +char * +ovsdb_wrapper_mcast_mac_remote_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + return mcast->MAC; +} + +char * +ovsdb_wrapper_mcast_mac_remote_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + if (mcast->logical_switch) + return mcast->logical_switch->name; + return NULL; +} + +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row) +{ + struct vteprec_mcast_macs_remote *mcast = + row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; + return &(mcast->locator_set->header_); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h new file mode 100644 index 00000000000..9823334c7d2 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ + +#include + +struct ovsdb_wrapper_port_vlan_binding { + int64_t vlan; + struct ovsdb_idl_row *ls; +}; + +/* Wrapper for C APIs */ +struct ovsdb_idl * ovsdb_wrapper_idl_create(); +void ovsdb_wrapper_idl_destroy(struct ovsdb_idl *idl); +const struct vteprec_global *ovsdb_wrapper_vteprec_global_first(struct ovsdb_idl *); +int ovsdb_wrapper_row_type(struct ovsdb_idl_row *row); +bool ovsdb_wrapper_msg_echo_req(struct jsonrpc_msg *msg); +bool ovsdb_wrapper_msg_echo_reply(struct jsonrpc_msg *msg); +struct jsonrpc_msg* ovsdb_wrapper_jsonrpc_create_reply(struct jsonrpc_msg *msg); + +void ovsdb_wrapper_idl_set_callback(struct ovsdb_idl *idl, void *idl_base, + void (*cb)(void*, int, struct ovsdb_idl_row *), + void (*ack_cb)(void*, struct ovsdb_idl_txn *)); +struct jsonrpc_msg *ovsdb_wrapper_idl_encode_monitor_request(struct ovsdb_idl *); +void ovsdb_wrapper_idl_msg_process(struct ovsdb_idl *, struct jsonrpc_msg *msg); +struct json *ovsdb_wrapper_jsonrpc_msg_to_json(struct jsonrpc_msg *); +char *ovsdb_wrapper_json_to_string(const struct json *, int); +void ovsdb_wrapper_json_destroy(struct json *); +struct json_parser *ovsdb_wrapper_json_parser_create(int); +size_t ovsdb_wrapper_json_parser_feed(struct json_parser *, const char *, size_t); +bool ovsdb_wrapper_json_parser_is_done(const struct json_parser *); +struct json *ovsdb_wrapper_json_parser_finish(struct json_parser *); +char *ovsdb_wrapper_jsonrpc_msg_from_json(struct json *, struct jsonrpc_msg **); +void ovsdb_wrapper_jsonrpc_msg_destroy(struct jsonrpc_msg *msg); + +struct ovsdb_idl_txn *ovsdb_wrapper_idl_txn_create(struct ovsdb_idl *idl); +void ovsdb_wrapper_idl_txn_destroy(struct ovsdb_idl_txn *txn); +bool ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn); +struct jsonrpc_msg *ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn); + +/* Physical Switch */ +char *ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row); + +/* Logical Switch */ +char *ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row); +int64_t ovsdb_wrapper_logical_switch_tunnel_key(struct ovsdb_idl_row *row); +struct ovsdb_idl_row *ovsdb_wrapper_add_logical_switch(struct ovsdb_idl_txn *, + struct ovsdb_idl_row *, const char *, int64_t); +void ovsdb_wrapper_delete_logical_switch(struct ovsdb_idl_row *); + +/* Physical Port */ +char *ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row); +size_t ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row); +void ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_binding*); +void ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *, struct ovsdb_idl_row *, + struct ovsdb_wrapper_port_vlan_binding*, size_t binding_count); + +/* Physical Locator */ +char *ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row); +void ovsdb_wrapper_add_physical_locator(struct ovsdb_idl_txn *, + struct ovsdb_idl_row *, const char *); +void ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *); + +/* unicast mac local */ +char *ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row); + +/* unicast mac remote */ + +/* multicast mac local */ +void ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_mcast_mac_local_mac(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_mcast_mac_local_logical_switch(struct ovsdb_idl_row *row); +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row); + +/* multicast mac remote */ +void ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, + struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, + const char *dst_ip); +void ovsdb_wrapper_delete_mcast_mac_remote(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_mcast_mac_remote_mac(struct ovsdb_idl_row *row); +char * +ovsdb_wrapper_mcast_mac_remote_logical_switch(struct ovsdb_idl_row *row); +struct ovsdb_idl_row * +ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row); + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc new file mode 100644 index 00000000000..eca1a644559 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +#include +#include +#include +#include + +using namespace AGENT; + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), + is_vxlan_nh_(true), nh_(NULL) { +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const PhysicalLocatorEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), + is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + const NextHop *entry) : OvsdbDBEntry(table), dip_(""), + is_vxlan_nh_(false), nh_(entry) { + if (entry->GetType() == NextHop::TUNNEL) { + const TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + dip_ = tunnel_nh->GetDip()->to_string(); + is_vxlan_nh_ = true; + } + } +} + +PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), + is_vxlan_nh_(true), nh_(NULL) { +} + +PhysicalLocatorEntry::~PhysicalLocatorEntry() { +} + +void PhysicalLocatorEntry::AddMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); +} + +void PhysicalLocatorEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void PhysicalLocatorEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_delete_physical_locator(ovs_entry_); +} + +bool PhysicalLocatorEntry::Sync(DBEntry *db_entry) { + NextHop *entry = static_cast(db_entry); + if (entry->GetType() == NextHop::TUNNEL) { + TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + if (dip_ != tunnel_nh->GetDip()->to_string()) { + // We don't handle dest ip change; + assert(0); + } + } + } + return false; +} + +bool PhysicalLocatorEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalLocatorEntry &pl_entry = + static_cast(entry); + if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { + return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); + } else if (!is_vxlan_nh_) { + return nh_ < pl_entry.nh_; + } + return (dip_ < pl_entry.dip_); +} + +KSyncEntry *PhysicalLocatorEntry::UnresolvedReference() { +#if 0 + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } +#endif + return NULL; +} + +PhysicalLocatorTable::PhysicalLocatorTable(OvsdbClientIdl *idl, + DBTable *table) : OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, + boost::bind(&PhysicalLocatorTable::OvsdbNotify, this, _1, _2)); +} + +PhysicalLocatorTable::~PhysicalLocatorTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR); +} + +void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + //NotifyDelete((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + //NotifyAdd((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +KSyncEntry *PhysicalLocatorTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalLocatorEntry *k_entry = + static_cast(key); + PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, k_entry); + return entry; +} + +KSyncEntry *PhysicalLocatorTable::DBToKSyncEntry(const DBEntry* db_entry) { + const NextHop *entry = + static_cast(db_entry); + PhysicalLocatorEntry *key = new PhysicalLocatorEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *PhysicalLocatorTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, row); + return static_cast(entry); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h new file mode 100644 index 00000000000..49485a8d419 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __PHYSICAL_LOCATOR_OVSDB_H__ +#define __PHYSICAL_LOCATOR_OVSDB_H__ + +#include + +class KSyncEntry; +class OvsdbDBEntry; +class PhysicalLocatorEntry; + +class PhysicalLocatorTable : public OvsdbDBObject { +public: + PhysicalLocatorTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~PhysicalLocatorTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + friend class PhysicalLocatorEntry; + DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorTable); +}; + +class PhysicalLocatorEntry : public OvsdbDBEntry { +public: + PhysicalLocatorEntry(PhysicalLocatorTable *table, const char *dip_str); + PhysicalLocatorEntry(PhysicalLocatorTable *table, + const PhysicalLocatorEntry *key); + PhysicalLocatorEntry(PhysicalLocatorTable *table, const NextHop *entry); + PhysicalLocatorEntry(PhysicalLocatorTable *table, struct ovsdb_idl_row *entry); + ~PhysicalLocatorEntry(); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Locator";} + KSyncEntry* UnresolvedReference(); +private: + friend class PhysicalLocatorTable; + std::string dip_; + bool is_vxlan_nh_; + const NextHop *nh_; + DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorEntry); +}; + +#endif //__PHYSICAL_LOCATOR_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc new file mode 100644 index 00000000000..70a25299bb9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +using OVSDB::PhysicalPortEntry; +using OVSDB::PhysicalPortTable; + +PhysicalPortEntry::PhysicalPortEntry(PhysicalPortTable *table, + const char *name) : OvsdbEntry(table), name_(name), binding_table_(), + ovs_binding_table_() { +} + +PhysicalPortEntry::PhysicalPortEntry(PhysicalPortTable *table, + const std::string &name) : OvsdbEntry(table), name_(name), + binding_table_(), ovs_binding_table_() { +} + +PhysicalPortEntry::~PhysicalPortEntry() { +} + +bool PhysicalPortEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalPortEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *PhysicalPortEntry::UnresolvedReference() { + return NULL; +} + +void PhysicalPortEntry::Encode(struct ovsdb_idl_txn *txn) { + if (GetState() == KSyncEntry::TEMP || IsDeleted()) { + /* + * we can only modify the vlan bindings in physical port + * table as we don't own the table, we are not suppose to create + * a new port entry in the table, so return from here if entry is + * marked temporary or deleted. + */ + return; + } + struct ovsdb_wrapper_port_vlan_binding binding[binding_table_.size()]; + VlanLSTable::iterator it = binding_table_.begin(); + std::size_t i = 0; + for ( ; it != binding_table_.end(); it++) { + struct ovsdb_idl_row *ls = it->second->ovs_entry(); + if (ls != NULL) { + binding[i].ls = ls; + binding[i].vlan = it->first; + i++; + } + } + ovsdb_wrapper_update_physical_port(txn, ovs_entry_, binding, i); +} + +void PhysicalPortEntry::AddBinding(int16_t vlan, LogicalSwitchEntry *ls) { +} + +void PhysicalPortEntry::DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls) { +} + +void PhysicalPortEntry::OverrideOvs() { + return; + //OvsdbDBObject *object = static_cast(GetObject()); + struct ovsdb_idl_txn *txn = table_->client_idl()->CreateTxn(this); + Encode(txn); + struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + if (msg == NULL) { + table_->client_idl()->DeleteTxn(txn); + return; + } + table_->client_idl()->SendJsonRpc(msg); +} + +PhysicalPortTable::PhysicalPortTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_PORT, + boost::bind(&PhysicalPortTable::Notify, this, _1, _2)); +} + +PhysicalPortTable::~PhysicalPortTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_PORT); +} + +void PhysicalPortTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + bool override_ovs = false; + PhysicalPortEntry *entry = NULL; + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Port %s\n", + ovsdb_wrapper_physical_port_name(row)); + PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Find(&key)); + if (entry != NULL) { + // TODO trigger notify delete for bindings + Delete(entry); + } + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Find(&key)); + if (entry == NULL) { + printf("Add/Change of Physical Port %s\n", + ovsdb_wrapper_physical_port_name(row)); + entry = static_cast(Create(&key)); + entry->ovs_entry_ = row; + } + PhysicalPortEntry::VlanLSTable old(entry->ovs_binding_table_); + std::size_t count = ovsdb_wrapper_physical_port_vlan_binding_count(row); + struct ovsdb_wrapper_port_vlan_binding new_bind[count]; + ovsdb_wrapper_physical_port_vlan_binding(row, new_bind); + for (std::size_t i = 0; i < count; i++) { + if (entry->binding_table_.find(new_bind[i].vlan) == + entry->binding_table_.end()) { + /* + * Entries present which are not owned by us, + * write port transaction to override the value. + */ + override_ovs = true; + continue; + } + LogicalSwitchEntry key(client_idl_->logical_switch_table(), + ovsdb_wrapper_logical_switch_name(new_bind[i].ls)); + LogicalSwitchEntry *ls_entry = + static_cast( + client_idl_->logical_switch_table()->Find(&key)); + entry->ovs_binding_table_[new_bind[i].vlan] = ls_entry; + old.erase(new_bind[i].vlan); + } + PhysicalPortEntry::VlanLSTable::iterator it = old.begin(); + for ( ; it != old.end(); it++) { + if (entry->binding_table_.find(it->first) != + entry->binding_table_.end()) { + /* + * Entry owned by us is somehow deleted, + * write port transaction to override the value. + */ + override_ovs = true; + } + entry->ovs_binding_table_.erase(it->first); + } + } else { + assert(0); + } + if (override_ovs) + entry->OverrideOvs(); +} + +KSyncEntry *PhysicalPortTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalPortEntry *k_entry = + static_cast(key); + PhysicalPortEntry *entry = new PhysicalPortEntry(this, k_entry->name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h new file mode 100644 index 00000000000..9c6837e3c89 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ + +#include +#include + +namespace OVSDB { +class PhysicalPortTable : public OvsdbObject { +public: + PhysicalPortTable(OvsdbClientIdl *idl); + virtual ~PhysicalPortTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(PhysicalPortTable); +}; + +class PhysicalPortEntry : public OvsdbEntry { +public: + typedef std::map VlanLSTable; + PhysicalPortEntry(PhysicalPortTable *table, const char *name); + PhysicalPortEntry(PhysicalPortTable *table, const std::string &name); + ~PhysicalPortEntry(); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Port";} + KSyncEntry* UnresolvedReference(); + void Encode(struct ovsdb_idl_txn *); + void AddBinding(int16_t vlan, LogicalSwitchEntry *ls); + void DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls); +private: + friend class PhysicalPortTable; + void OverrideOvs(); + std::string name_; + struct ovsdb_idl_row *ovs_entry_; + VlanLSTable binding_table_; + VlanLSTable ovs_binding_table_; + DISALLOW_COPY_AND_ASSIGN(PhysicalPortEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_PORT_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc new file mode 100644 index 00000000000..bb7f44a608b --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include + +using OVSDB::PhysicalSwitchEntry; +using OVSDB::PhysicalSwitchTable; + +PhysicalSwitchEntry::PhysicalSwitchEntry(PhysicalSwitchTable *table, + const std::string &name) : OvsdbEntry(table), name_(name) { +} + +PhysicalSwitchEntry::~PhysicalSwitchEntry() { +} + +bool PhysicalSwitchEntry::IsLess(const KSyncEntry &entry) const { + const PhysicalSwitchEntry &ps_entry = + static_cast(entry); + return (name_.compare(ps_entry.name_) < 0); +} + +KSyncEntry *PhysicalSwitchEntry::UnresolvedReference() { + return NULL; +} + +PhysicalSwitchTable::PhysicalSwitchTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH, + boost::bind(&PhysicalSwitchTable::Notify, this, _1, _2)); +} + +PhysicalSwitchTable::~PhysicalSwitchTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH); +} + +void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Switch %s\n", + ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry *entry = + static_cast(Find(&key)); + if (entry != NULL) + Delete(entry); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Switch %s\n", + ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry *entry = + static_cast(Find(&key)); + if (entry == NULL) { + Create(&key); + } + } else { + assert(0); + } +} + +KSyncEntry *PhysicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { + const PhysicalSwitchEntry *k_entry = + static_cast(key); + PhysicalSwitchEntry *entry = new PhysicalSwitchEntry(this, k_entry->name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h new file mode 100644 index 00000000000..50ecf5e7b71 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ + +#include +#include + +namespace OVSDB { +class PhysicalSwitchTable : public OvsdbObject { +public: + PhysicalSwitchTable(OvsdbClientIdl *idl); + virtual ~PhysicalSwitchTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchTable); +}; + +class PhysicalSwitchEntry : public OvsdbEntry { +public: + PhysicalSwitchEntry(PhysicalSwitchTable *table, const std::string &name); + ~PhysicalSwitchEntry(); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Physical Switch";} + KSyncEntry* UnresolvedReference(); +private: + PhysicalSwitchEntry(PhysicalSwitchTable *table, const PhysicalSwitchEntry *key); + + friend class PhysicalSwitchTable; + std::string name_; + DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_SWITCH_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc new file mode 100644 index 00000000000..cee5ccc3fb9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include + +UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalTable *table, + struct ovsdb_idl_row *ovsdb_row, std::string mac, std::string ip_addr, + std::string ls_name) : OvsdbEntry(table), + ovsdb_row_(ovsdb_row), mac_(mac), ip_addr_(ip_addr), ls_name_(ls_name) { +} + +bool UnicastMacLocalEntry::IsLess(const KSyncEntry &entry) const { + const UnicastMacLocalEntry &uc_entry = + static_cast(entry); + return (ovsdb_row_ < uc_entry.ovsdb_row_); +} + +KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() { + return NULL; +} + +UnicastMacLocalTable::UnicastMacLocalTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { + idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, + boost::bind(&UnicastMacLocalTable::Notify, this, _1, _2)); +} + +UnicastMacLocalTable::~UnicastMacLocalTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL); +} + +void UnicastMacLocalTable::Notify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + /* if logical switch is not avialable, trigger entry delete */ + bool delete_entry = + (ovsdb_wrapper_ucast_mac_local_logical_switch(row) == NULL); + const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row); + if (ls_name == NULL) + ls_name = ""; + UnicastMacLocalEntry key(this, row, ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + UnicastMacLocalEntry *entry = + static_cast(Find(&key)); + if (op == OvsdbClientIdl::OVSDB_DEL || delete_entry) { + printf("Delete of unicast local mac %s, IP %s, Logical Switch %s\n", + ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + if (entry != NULL) + Delete(entry); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of unicast local mac %s, IP %s, Logical Switch %s\n", + ovsdb_wrapper_ucast_mac_local_mac(row), + ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); + if (entry == NULL) + Create(&key); + } else { + assert(0); + } +} + +KSyncEntry *UnicastMacLocalTable::Alloc(const KSyncEntry *key, uint32_t index) { + const UnicastMacLocalEntry *k_entry = + static_cast(key); + UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, + k_entry->ovsdb_row_, k_entry->mac_, k_entry->ip_addr_, + k_entry->ls_name_); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h new file mode 100644 index 00000000000..b281ecadc67 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __UNICAST_MAC_LOCAL_OVSDB_H__ +#define __UNICAST_MAC_LOCAL_OVSDB_H__ + +#include + +class UnicastMacLocalTable : public OvsdbObject { +public: + UnicastMacLocalTable(OvsdbClientIdl *idl); + virtual ~UnicastMacLocalTable(); + + void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); +private: + DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalTable); +}; + +class UnicastMacLocalEntry : public OvsdbEntry { +public: + UnicastMacLocalEntry(UnicastMacLocalTable *table, + struct ovsdb_idl_row *ovsdb_row, std::string mac, + std::string ip_addr, std::string ls_name); + + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Unicast Mac Local";} + KSyncEntry* UnresolvedReference(); +private: + friend class UnicastMacLocalTable; + struct ovsdb_idl_row *ovsdb_row_; + std::string mac_; + std::string ip_addr_; + std::string ls_name_; + UnicastMacLocalTable *table_; +}; + +#endif //__UNICAST_MAC_LOCAL_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc new file mode 100644 index 00000000000..27db947ed66 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; + +#include +#include + +#include +#include +#include +#include + +using namespace AGENT; + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), + is_vxlan_nh_(true), nh_(NULL) { +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const UnicastMacRemoteEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), + is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const NextHop *entry) : OvsdbDBEntry(table), dip_(""), + is_vxlan_nh_(false), nh_(entry) { + if (entry->GetType() == NextHop::TUNNEL) { + const TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + dip_ = tunnel_nh->GetDip()->to_string(); + is_vxlan_nh_ = true; + } + } +} + +UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), + is_vxlan_nh_(true), nh_(NULL) { +} + +UnicastMacRemoteEntry::~UnicastMacRemoteEntry() { +} + +void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); +} + +void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + AddMsg(txn); +} + +void UnicastMacRemoteEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!is_vxlan_nh_) + return; + ovsdb_wrapper_delete_physical_locator(ovs_entry_); +} + +bool UnicastMacRemoteEntry::Sync(DBEntry *db_entry) { + NextHop *entry = static_cast(db_entry); + if (entry->GetType() == NextHop::TUNNEL) { + TunnelNH *tunnel_nh = static_cast(entry); + if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { + if (dip_ != tunnel_nh->GetDip()->to_string()) { + // We don't handle dest ip change; + assert(0); + } + } + } + return false; +} + +bool UnicastMacRemoteEntry::IsLess(const KSyncEntry &entry) const { + const UnicastMacRemoteEntry &pl_entry = + static_cast(entry); + if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { + return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); + } else if (!is_vxlan_nh_) { + return nh_ < pl_entry.nh_; + } + return (dip_ < pl_entry.dip_); +} + +KSyncEntry *UnicastMacRemoteEntry::UnresolvedReference() { +#if 0 + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + PhysicalSwitchEntry *p_switch = + static_cast(p_table->GetReference(&key)); + if (!p_switch->IsResolved()) { + return p_switch; + } +#endif + return NULL; +} + +UnicastMacRemoteTable::UnicastMacRemoteTable(OvsdbClientIdl *idl, + DBTable *table) : OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, + boost::bind(&UnicastMacRemoteTable::OvsdbNotify, this, _1, _2)); +} + +UnicastMacRemoteTable::~UnicastMacRemoteTable() { + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR); +} + +void UnicastMacRemoteTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + if (op == OvsdbClientIdl::OVSDB_DEL) { + printf("Delete of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + NotifyDelete((OvsdbDBEntry*)&key); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + printf("Add/Change of Physical Locator %s\n", + ovsdb_wrapper_physical_locator_dst_ip(row)); + UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); + NotifyAdd((OvsdbDBEntry*)&key, row); + } else { + assert(0); + } +} + +KSyncEntry *UnicastMacRemoteTable::Alloc(const KSyncEntry *key, uint32_t index) { + const UnicastMacRemoteEntry *k_entry = + static_cast(key); + UnicastMacRemoteEntry *entry = new UnicastMacRemoteEntry(this, k_entry); + return entry; +} + +KSyncEntry *UnicastMacRemoteTable::DBToKSyncEntry(const DBEntry* db_entry) { + const NextHop *entry = + static_cast(db_entry); + UnicastMacRemoteEntry *key = new UnicastMacRemoteEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *UnicastMacRemoteTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + UnicastMacRemoteEntry *entry = new UnicastMacRemoteEntry(this, row); + return static_cast(entry); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h new file mode 100644 index 00000000000..94cee9c1662 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __UNICAST_MAC_REMOTE_OVSDB_H__ +#define __UNICAST_MAC_REMOTE_OVSDB_H__ + +#include + +class KSyncEntry; +class OvsdbDBEntry; +class UnicastMacRemoteEntry; + +class UnicastMacRemoteTable : public OvsdbDBObject { +public: + UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~UnicastMacRemoteTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); +private: + friend class UnicastMacRemoteEntry; + DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteTable); +}; + +class UnicastMacRemoteEntry : public OvsdbDBEntry { +public: + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + std::string l_switch_name, MacAddress mac_, std::string dest_ip); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + const UnicastMacRemoteEntry *key); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, const NextHop *entry); + UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + struct ovsdb_idl_row *entry); + ~UnicastMacRemoteEntry(); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Unicast Remote Entry";} + KSyncEntry* UnresolvedReference(); +private: + friend class UnicastMacRemoteTable; + std::string l_switch_name_; + MacAddress mac_; + std::string dest_ip_; + + DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteEntry); +}; + +#endif //__UNICAST_MAC_REMOTE_OVSDB_H__ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc new file mode 100644 index 00000000000..989642bb2b3 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using OVSDB::VlanPortBindingEntry; +using OVSDB::VlanPortBindingTable; +using OVSDB::PhysicalPortEntry; +using OVSDB::LogicalSwitchEntry; + +VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, + const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_) { + logical_switch_name_ = entry->vm_interface()->vn()->GetName(); + physical_port_name_ = entry->physical_port()->name(); + vlan_ = entry->vlan(); +} + +VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, + const VlanPortBindingEntry *key) : OvsdbDBEntry(table) { + logical_switch_name_ = key->logical_switch_name_; + physical_port_name_ = key->physical_port_name_; + vlan_ = key->vlan_; +} + +void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) { + PhysicalPortTable *p_table = table_->client_idl()->physical_port_table(); + PhysicalPortEntry key(p_table, physical_port_name_.c_str()); + physical_port_ = p_table->GetReference(&key); + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + logical_switch_ = l_table->GetReference(&ls_key); + + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->AddBinding(vlan_, + static_cast(logical_switch_.get())); + port->Encode(txn); +} + +void VlanPortBindingEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { + if (physical_port_) { + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->DeleteBinding(vlan_, + static_cast(logical_switch_.get())); + physical_port_ = NULL; + logical_switch_ = NULL; + } + AddMsg(txn); +} + +void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + if (!physical_port_) { + return; + } + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->DeleteBinding(vlan_, + static_cast(logical_switch_.get())); + physical_port_ = NULL; + logical_switch_ = NULL; + port->Encode(txn); +} + +bool VlanPortBindingEntry::Sync(DBEntry *db_entry) { + return false; +} + +bool VlanPortBindingEntry::IsLess(const KSyncEntry &entry) const { + const VlanPortBindingEntry &vps_entry = + static_cast(entry); + if (vlan_ != vps_entry.vlan_) + return vlan_ < vps_entry.vlan_; + if (physical_port_name_ != vps_entry.physical_port_name_) + return physical_port_name_ < vps_entry.physical_port_name_; + + return logical_switch_name_ < vps_entry.logical_switch_name_; +} + +KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { + PhysicalPortTable *p_table = table_->client_idl()->physical_port_table(); + PhysicalPortEntry key(p_table, physical_port_name_.c_str()); + PhysicalPortEntry *p_port = + static_cast(p_table->GetReference(&key)); + if (!p_port->IsResolved()) { + return p_port; + } + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *ls_entry = + static_cast(l_table->GetReference(&ls_key)); + if (!ls_entry->IsResolved()) { + return ls_entry; + } + return NULL; +} + +VlanPortBindingTable::VlanPortBindingTable(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { +} + +VlanPortBindingTable::~VlanPortBindingTable() { +} + +void VlanPortBindingTable::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { +} + +KSyncEntry *VlanPortBindingTable::Alloc(const KSyncEntry *key, uint32_t index) { + const VlanPortBindingEntry *k_entry = + static_cast(key); + VlanPortBindingEntry *entry = new VlanPortBindingEntry(this, k_entry); + return entry; +} + +KSyncEntry *VlanPortBindingTable::DBToKSyncEntry(const DBEntry* db_entry) { + const AGENT::VlanLogicalPortEntry *entry = + static_cast(db_entry); + VlanPortBindingEntry *key = new VlanPortBindingEntry(this, entry); + return static_cast(key); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h new file mode 100644 index 00000000000..851531ab705 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ + +#include +#include + +namespace AGENT { +class PhysicalDeviceVnEntry; +class VlanLogicalPortEntry; +}; + +namespace OVSDB { +class VlanPortBindingTable : public OvsdbDBObject { +public: + VlanPortBindingTable(OvsdbClientIdl *idl, DBTable *table); + virtual ~VlanPortBindingTable(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row*); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); +private: + DISALLOW_COPY_AND_ASSIGN(VlanPortBindingTable); +}; + +class VlanPortBindingEntry : public OvsdbDBEntry { +public: + VlanPortBindingEntry(VlanPortBindingTable *table, + const VlanPortBindingEntry *key); + VlanPortBindingEntry(VlanPortBindingTable *table, + const AGENT::VlanLogicalPortEntry *entry); + + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "Vlan Port Binding";} + KSyncEntry* UnresolvedReference(); +private: + friend class VlanPortBindingTable; + KSyncEntryPtr logical_switch_; + KSyncEntryPtr physical_port_; + std::string physical_port_name_; + std::string logical_switch_name_; + uint16_t vlan_; + DISALLOW_COPY_AND_ASSIGN(VlanPortBindingEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VLAN_PORT_BINDING_OVSDB_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc index f9bb251d26a..feb5980f53f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc @@ -30,11 +30,13 @@ #include #include #include +#include #include using std::string; using std::cout; +using OVSDB::OvsdbClient; TorAgentInit::TorAgentInit() { } @@ -78,6 +80,8 @@ void TorAgentInit::CreatePeers() { void TorAgentInit::CreateModules() { device_manager_.reset(new PhysicalDeviceManager(agent())); agent()->set_device_manager(device_manager_.get()); + ovsdb_client_.reset(OvsdbClient::Allocate(agent(), + static_cast(agent_param()))); } void TorAgentInit::CreateDBTables() { @@ -86,6 +90,7 @@ void TorAgentInit::CreateDBTables() { void TorAgentInit::RegisterDBClients() { device_manager_->RegisterDBClients(); + ovsdb_client_->RegisterClients(); } void TorAgentInit::InitModules() { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h index f2b5da8a0b6..e107e8c70a9 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h @@ -14,6 +14,9 @@ class Agent; class AgentParam; class PhysicalDeviceManager; class OvsPeerManager; +namespace OVSDB { +class OvsdbClient; +}; // The class to drive agent initialization. // Defines control parameters used to enable/disable agent features @@ -44,10 +47,12 @@ class TorAgentInit : public AgentInit { // Accessor methods PhysicalDeviceManager *device_manager() const; OvsPeerManager *ovs_peer_manager() const; + OVSDB::OvsdbClient *ovsdb_client() {return ovsdb_client_.get();} private: std::auto_ptr device_manager_; std::auto_ptr ovs_peer_manager_; + std::auto_ptr ovsdb_client_; DISALLOW_COPY_AND_ASSIGN(TorAgentInit); }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc index 8492ccc13d6..58ae336c0bd 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.cc @@ -27,6 +27,8 @@ void TorAgentParam::AddOptions() { tor.add_options() ("TOR.tor_ip", boost_po::value()->default_value(""), "IP Address of the ToR being managed") + ("TOR.tsn_ip", boost_po::value()->default_value(""), + "IP Address of the ToR Service Node") ("TOR.tor_id", boost_po::value()->default_value(""), "Identifier of the TOR"); AgentParam::AddOptions(tor); @@ -39,6 +41,7 @@ void TorAgentParam::InitFromConfig() { // Parse ToR specific arguments ParseIp("TOR.tor_ip", &tor_info_.ip_); + ParseIp("TOR.tsn_ip", &tor_info_.tsn_ip_); GetValueFromTree(tor_info_.id_, "TOR.tor_id"); GetValueFromTree(tor_info_.type_, "TOR.tor_type"); GetValueFromTree(tor_info_.protocol_, "TOR.tor_ovs_protocol"); @@ -53,6 +56,7 @@ void TorAgentParam::InitFromArguments() { boost::program_options::variables_map vars = var_map(); ParseIpArgument(vars, tor_info_.ip_, "TOR.tor_ip"); + ParseIpArgument(vars, tor_info_.tsn_ip_, "TOR.tsn_ip"); GetOptValue(vars, tor_info_.id_, "TOR.tor_id"); GetOptValue(vars, tor_info_.type_, "TOR.tor_type"); GetOptValue(vars, tor_info_.protocol_, "TOR.tor_ovs_protocol"); @@ -65,6 +69,11 @@ int TorAgentParam::Validate() { return (EINVAL); } + if (tor_info_.tsn_ip_ == Ip4Address::from_string("0.0.0.0")) { + LOG(ERROR, "Configuration error. TSN IP address not specified"); + return (EINVAL); + } + if (tor_info_.id_ == "") { LOG(ERROR, "Configuration error. ToR ID not specified"); return (EINVAL); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h index abd9914e67b..9735abdee60 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_param.h @@ -20,6 +20,7 @@ class TorAgentParam : public AgentParam { struct TorInfo { std::string type_; Ip4Address ip_; + Ip4Address tsn_ip_; std::string id_; // Protocol to connect to ToR std::string protocol_; @@ -33,6 +34,10 @@ class TorAgentParam : public AgentParam { void AddOptions(); std::string tor_id() const { return tor_info_.id_; } + std::string tor_protocol() const { return tor_info_.protocol_; } + Ip4Address tor_ip() const { return tor_info_.ip_; } + Ip4Address tsn_ip() const { return tor_info_.tsn_ip_; } + int tor_port() const { return tor_info_.port_; } private: virtual void InitFromConfig(); From dce81ae3c6746a68c364385e51b0ceb26cc646b2 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sat, 18 Oct 2014 17:57:00 +0530 Subject: [PATCH 003/218] Set display-name as name for physical-router, physical-interface and logical-interface --- .../physical_devices/tables/logical_port.cc | 10 ++++- .../physical_devices/tables/logical_port.h | 20 ++++++---- .../tables/physical_device.cc | 11 +++++- .../physical_devices/tables/physical_device.h | 12 ++++-- .../tables/physical_devices.sandesh | 38 +++++++++++-------- .../physical_devices/tables/physical_port.cc | 9 ++++- .../physical_devices/tables/physical_port.h | 8 +++- 7 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/vnsw/agent/physical_devices/tables/logical_port.cc b/src/vnsw/agent/physical_devices/tables/logical_port.cc index 7c24158f71d..cb28a7909b7 100644 --- a/src/vnsw/agent/physical_devices/tables/logical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/logical_port.cc @@ -58,6 +58,11 @@ bool LogicalPortEntry::CopyBase(LogicalPortTable *table, const LogicalPortData *data) { bool ret = false; + if (fq_name_ != data->fq_name_) { + fq_name_ = data->fq_name_; + ret = true; + } + if (name_ != data->name_) { name_ = data->name_; ret = true; @@ -179,7 +184,8 @@ static LogicalPortData *BuildData(const Agent *agent, IFMapNode *node, vmi_uuid); } - return new LogicalPortData(node->name(), physical_port_uuid, vmi_uuid); + return new LogicalPortData(node->name(), port->display_name(), + physical_port_uuid, vmi_uuid); } bool LogicalPortTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -219,6 +225,7 @@ class LogicalPortSandesh : public AgentSandesh { static void SetLogicalPortSandeshData(const LogicalPortEntry *entry, SandeshLogicalPort *data) { data->set_uuid(UuidToString(entry->uuid())); + data->set_fq_name(entry->fq_name()); data->set_name(entry->name()); if (entry->physical_port()) { data->set_physical_port(entry->physical_port()->name()); @@ -270,6 +277,7 @@ void LogicalPortEntry::SendObjectLog(AgentLogEvent::type event) const { info.set_event(str); info.set_uuid(UuidToString(uuid_)); + info.set_fq_name(fq_name_); info.set_name(name_); if (physical_port_) { info.set_physical_port(physical_port_->name()); diff --git a/src/vnsw/agent/physical_devices/tables/logical_port.h b/src/vnsw/agent/physical_devices/tables/logical_port.h index 2e2b1626d1b..659a67b5895 100644 --- a/src/vnsw/agent/physical_devices/tables/logical_port.h +++ b/src/vnsw/agent/physical_devices/tables/logical_port.h @@ -24,7 +24,7 @@ class LogicalPortEntry : AgentRefCount, public AgentDBEntry { }; explicit LogicalPortEntry(const boost::uuids::uuid &id) : - uuid_(id), name_(), physical_port_(), vm_interface_() { } + uuid_(id), fq_name_(), physical_port_(), vm_interface_() { } virtual ~LogicalPortEntry() { } virtual bool IsLess(const DBEntry &rhs) const; @@ -35,6 +35,7 @@ class LogicalPortEntry : AgentRefCount, public AgentDBEntry { } const boost::uuids::uuid &uuid() const { return uuid_; } + const std::string &fq_name() const { return fq_name_; } const std::string &name() const { return name_; } PhysicalPortEntry *physical_port() const { return physical_port_.get(); } VmInterface *vm_interface() const; @@ -48,6 +49,7 @@ class LogicalPortEntry : AgentRefCount, public AgentDBEntry { private: friend class LogicalPortTable; boost::uuids::uuid uuid_; + std::string fq_name_; std::string name_; PhysicalPortEntryRef physical_port_; InterfaceRef vm_interface_; @@ -94,11 +96,14 @@ struct LogicalPortKey : public AgentKey { }; struct LogicalPortData : public AgentData { - LogicalPortData(const std::string &name, const boost::uuids::uuid &port, + LogicalPortData(const std::string &fq_name, const std::string &name, + const boost::uuids::uuid &port, const boost::uuids::uuid &vif) : - name_(name), physical_port_(port), vm_interface_(vif) { } + fq_name_(fq_name), name_(name), physical_port_(port), + vm_interface_(vif) { } virtual ~LogicalPortData() { } + std::string fq_name_; std::string name_; boost::uuids::uuid physical_port_; boost::uuids::uuid vm_interface_; @@ -113,9 +118,10 @@ struct VlanLogicalPortKey : public LogicalPortKey { }; struct VlanLogicalPortData : public LogicalPortData { - VlanLogicalPortData(const std::string &name, const boost::uuids::uuid &port, + VlanLogicalPortData(const std::string &fq_name, const std::string &name, + const boost::uuids::uuid &port, const boost::uuids::uuid &vif, uint16_t vlan) : - LogicalPortData(name, port, vif), vlan_(vlan) { } + LogicalPortData(fq_name, name, port, vif), vlan_(vlan) { } virtual ~VlanLogicalPortData() { } uint16_t vlan_; @@ -145,10 +151,10 @@ struct DefaultLogicalPortKey : public LogicalPortKey { }; struct DefaultLogicalPortData : public LogicalPortData { - DefaultLogicalPortData(const std::string &name, + DefaultLogicalPortData(const std::string &fq_name, const std::string &name, const boost::uuids::uuid &port, const boost::uuids::uuid &vif) : - LogicalPortData(name, port, vif) { } + LogicalPortData(fq_name, name, port, vif) { } virtual ~DefaultLogicalPortData() { } }; diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.cc b/src/vnsw/agent/physical_devices/tables/physical_device.cc index 24c2c92e07a..d257dfa30de 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device.cc @@ -72,6 +72,11 @@ void PhysicalDeviceEntry::SetKey(const DBRequestKey *key) { bool PhysicalDeviceEntry::Copy(const PhysicalDeviceData *data) { bool ret = false; + if (fq_name_ != data->fq_name_) { + fq_name_ = data->fq_name_; + ret = true; + } + if (name_ != data->name_) { name_ = data->name_; ret = true; @@ -174,8 +179,8 @@ static PhysicalDeviceData *BuildData(const IFMapNode *node, IpAddress ip = IpAddress::from_string(router->dataplane_ip(), ec); IpAddress mip = IpAddress::from_string(router->management_ip(), ec); assert(!ec); - return new PhysicalDeviceData(node->name(), router->vendor_name(), - ip, mip, "ovs"); + return new PhysicalDeviceData(node->name(), router->display_name(), + router->vendor_name(), ip, mip, "OVS"); } bool PhysicalDeviceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -221,6 +226,7 @@ class DeviceSandesh : public AgentSandesh { static void SetDeviceSandeshData(const PhysicalDeviceEntry *entry, SandeshDevice *data) { data->set_uuid(UuidToString(entry->uuid())); + data->set_fq_name(entry->fq_name()); data->set_name(entry->name()); data->set_vendor(entry->vendor()); data->set_ip_address(entry->ip().to_string()); @@ -272,6 +278,7 @@ void PhysicalDeviceEntry::SendObjectLog(AgentLogEvent::type event) const { info.set_event(str); info.set_uuid(UuidToString(uuid_)); + info.set_fq_name(fq_name_); info.set_name(name_); info.set_vendor(vendor_); info.set_ip_address(ip_.to_string()); diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.h b/src/vnsw/agent/physical_devices/tables/physical_device.h index 821949810b2..38764b6e66c 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.h +++ b/src/vnsw/agent/physical_devices/tables/physical_device.h @@ -19,13 +19,15 @@ struct PhysicalDeviceKey : public AgentKey { }; struct PhysicalDeviceData : public AgentData { - PhysicalDeviceData(const std::string &name, const std::string &vendor, - const IpAddress &ip, const IpAddress &mgmt_ip, - const std::string &protocol) : - AgentData(), name_(name), vendor_(vendor), ip_(ip), + PhysicalDeviceData(const std::string &fq_name, const std::string &name, + const std::string &vendor, + const IpAddress &ip, const IpAddress &mgmt_ip, + const std::string &protocol) : + AgentData(), fq_name_(fq_name), name_(name), vendor_(vendor), ip_(ip), management_ip_(mgmt_ip), protocol_(protocol) { } virtual ~PhysicalDeviceData() { } + std::string fq_name_; std::string name_; std::string vendor_; IpAddress ip_; @@ -55,6 +57,7 @@ class PhysicalDeviceEntry : AgentRefCount, bool Copy(const PhysicalDeviceData *data); const boost::uuids::uuid &uuid() const { return uuid_; } + const std::string &fq_name() const { return fq_name_; } const std::string &name() const { return name_; } const std::string &vendor() const { return vendor_; } const IpAddress &ip() const { return ip_; } @@ -67,6 +70,7 @@ class PhysicalDeviceEntry : AgentRefCount, private: friend class PhysicalDeviceTable; boost::uuids::uuid uuid_; + std::string fq_name_; std::string name_; std::string vendor_; IpAddress ip_; diff --git a/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh b/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh index 9fdcd7eea25..0a8cc617f75 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh +++ b/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh @@ -7,10 +7,11 @@ ****************************************************************************/ struct SandeshDevice { 1: string uuid; - 2: string name; - 3: string vendor; - 4: string ip_address; - 5: string management_protocol; + 2: string fq_name; + 3: string name; + 4: string vendor; + 5: string ip_address; + 6: string management_protocol; } response sandesh SandeshDeviceListResp { @@ -25,10 +26,11 @@ struct DeviceObjectLogInfo { 1: string event; 2: string uuid; 3: i32 ref_count; - 4: string name; - 5: string vendor; - 6: string ip_address; - 7: string management_protocol; + 4: string fq_name; + 5: string name; + 6: string vendor; + 7: string ip_address; + 8: string management_protocol; } objectlog sandesh DeviceObjectLog { @@ -42,8 +44,9 @@ struct PhysicalPortObjectLogInfo { 1: string event; 2: string uuid; 3: i32 ref_count; - 4: string name; - 5: string device; + 4: string fq_name; + 5: string name; + 6: string device; } objectlog sandesh PhysicalPortObjectLog { @@ -52,8 +55,9 @@ objectlog sandesh PhysicalPortObjectLog { struct SandeshPhysicalPort { 1: string uuid; - 2: string name; - 3: string device; + 2: string fq_name; + 3: string name; + 4: string device; } response sandesh SandeshPhysicalPortListResp { @@ -70,8 +74,9 @@ request sandesh SandeshPhysicalPortReq { ****************************************************************************/ struct SandeshLogicalPort { 1: string uuid; - 2: string name; - 3: string physical_port; + 2: string fq_name; + 3: string name; + 4: string physical_port; } response sandesh SandeshLogicalPortListResp { @@ -87,8 +92,9 @@ struct LogicalPortObjectLogInfo { 1: string event; 2: string uuid; 3: i32 ref_count; - 4: string name; - 5: string physical_port; + 4: string fq_name; + 5: string name; + 6: string physical_port; } objectlog sandesh LogicalPortObjectLog { diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.cc b/src/vnsw/agent/physical_devices/tables/physical_port.cc index 102710bdb03..f0927f03ebb 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_port.cc @@ -53,6 +53,11 @@ bool PhysicalPortEntry::Copy(PhysicalPortTable *table, const PhysicalPortData *data) { bool ret = false; + if (fq_name_ != data->fq_name_) { + fq_name_ = data->fq_name_; + ret = true; + } + if (name_ != data->name_) { name_ = data->name_; ret = true; @@ -148,7 +153,7 @@ static PhysicalPortData *BuildData(const Agent *agent, IFMapNode *node, dev_uuid); } - return new PhysicalPortData(node->name(), dev_uuid); + return new PhysicalPortData(node->name(), port->display_name(), dev_uuid); } bool PhysicalPortTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -188,6 +193,7 @@ class AgentPhysicalPortSandesh : public AgentSandesh { static void SetPhysicalPortSandeshData(const PhysicalPortEntry *entry, SandeshPhysicalPort *data) { data->set_uuid(UuidToString(entry->uuid())); + data->set_fq_name(entry->fq_name()); data->set_name(entry->name()); if (entry->device()) { data->set_device(entry->device()->name()); @@ -240,6 +246,7 @@ void PhysicalPortEntry::SendObjectLog(AgentLogEvent::type event) const { info.set_event(str); info.set_uuid(UuidToString(uuid_)); + info.set_fq_name(fq_name_); info.set_name(name_); if (device_) { info.set_device(device_->name()); diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.h b/src/vnsw/agent/physical_devices/tables/physical_port.h index 3659e45b765..6f85be1b79d 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.h +++ b/src/vnsw/agent/physical_devices/tables/physical_port.h @@ -20,10 +20,12 @@ struct PhysicalPortKey : public AgentKey { }; struct PhysicalPortData : public AgentData { - PhysicalPortData(const std::string &name, const boost::uuids::uuid &dev) : - name_(name), device_(dev) { } + PhysicalPortData(const std::string fq_name, const std::string &name, + const boost::uuids::uuid &dev) : + fq_name_(fq_name), name_(name), device_(dev) { } virtual ~PhysicalPortData() { } + std::string fq_name_; std::string name_; boost::uuids::uuid device_; }; @@ -43,6 +45,7 @@ class PhysicalPortEntry : AgentRefCount, public AgentDBEntry{ } const boost::uuids::uuid &uuid() const { return uuid_; } + const std::string &fq_name() const { return fq_name_; } const std::string &name() const { return name_; } PhysicalDeviceEntry *device() const { return device_.get(); } @@ -54,6 +57,7 @@ class PhysicalPortEntry : AgentRefCount, public AgentDBEntry{ private: friend class PhysicalPortTable; boost::uuids::uuid uuid_; + std::string fq_name_; std::string name_; PhysicalDeviceEntryRef device_; DISALLOW_COPY_AND_ASSIGN(PhysicalPortEntry); From 75d5b645f3c74e4e94398de54ffd2b8fb2b6377b Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sat, 18 Oct 2014 23:18:38 +0530 Subject: [PATCH 004/218] Integration fixes 1. Avoid agent crash when dataplane_ip or management_ip is not specified 2. Add introspect to show VMI and tag for logical-port 3. Create VlanLogicalPortEntry --- .../physical_devices/tables/logical_port.cc | 27 +++++++++++++++---- .../physical_devices/tables/logical_port.h | 3 +++ .../tables/physical_device.cc | 7 ++--- .../tables/physical_device_vn.cc | 2 +- .../tables/physical_devices.sandesh | 4 +++ .../physical_devices/tables/physical_port.cc | 2 +- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/vnsw/agent/physical_devices/tables/logical_port.cc b/src/vnsw/agent/physical_devices/tables/logical_port.cc index cb28a7909b7..fef4ea32cad 100644 --- a/src/vnsw/agent/physical_devices/tables/logical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/logical_port.cc @@ -153,13 +153,13 @@ static LogicalPortKey *BuildKey(const autogen::LogicalInterface *port) { autogen::IdPermsType id_perms = port->id_perms(); boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); - return new DefaultLogicalPortKey(u); + return new VlanLogicalPortKey(u); } static LogicalPortData *BuildData(const Agent *agent, IFMapNode *node, const autogen::LogicalInterface *port) { // Find link with physical-interface adjacency - boost::uuids::uuid physical_port_uuid; + boost::uuids::uuid physical_port_uuid = nil_uuid(); IFMapNode *adj_node = NULL; adj_node = agent->cfg_listener()->FindAdjacentIFMapNode (agent, node, "physical-interface"); @@ -172,7 +172,7 @@ static LogicalPortData *BuildData(const Agent *agent, IFMapNode *node, } // Find link with virtual-machine-interface adjacency - boost::uuids::uuid vmi_uuid; + boost::uuids::uuid vmi_uuid = nil_uuid(); adj_node = agent->cfg_listener()->FindAdjacentIFMapNode (agent, node, "virtual-machine-interface"); if (adj_node) { @@ -184,8 +184,11 @@ static LogicalPortData *BuildData(const Agent *agent, IFMapNode *node, vmi_uuid); } - return new LogicalPortData(node->name(), port->display_name(), - physical_port_uuid, vmi_uuid); + return new AGENT::VlanLogicalPortData(node->name(), + port->display_name(), + physical_port_uuid, + vmi_uuid, + port->vlan_tag()); } bool LogicalPortTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -222,6 +225,9 @@ class LogicalPortSandesh : public AgentSandesh { } }; +void LogicalPortEntry::SetSandeshData(SandeshLogicalPort *data) const { +} + static void SetLogicalPortSandeshData(const LogicalPortEntry *entry, SandeshLogicalPort *data) { data->set_uuid(UuidToString(entry->uuid())); @@ -232,6 +238,13 @@ static void SetLogicalPortSandeshData(const LogicalPortEntry *entry, } else { data->set_physical_port("INVALID"); } + + if (entry->vm_interface()) { + data->set_physical_port(entry->vm_interface()->name()); + } else { + data->set_physical_port("INVALID"); + } + entry->SetSandeshData(data); } bool LogicalPortEntry::DBEntrySandesh(Sandesh *resp, std::string &name) const { @@ -316,6 +329,10 @@ bool VlanLogicalPortEntry::Copy(LogicalPortTable *table, return ret; } +void VlanLogicalPortEntry::SetSandeshData(SandeshLogicalPort *data) const { + data->set_vlan_tag(vlan_); +} + ////////////////////////////////////////////////////////////////////////////// // DefaultLogicalPort routines ////////////////////////////////////////////////////////////////////////////// diff --git a/src/vnsw/agent/physical_devices/tables/logical_port.h b/src/vnsw/agent/physical_devices/tables/logical_port.h index 659a67b5895..cd15bb1fbbb 100644 --- a/src/vnsw/agent/physical_devices/tables/logical_port.h +++ b/src/vnsw/agent/physical_devices/tables/logical_port.h @@ -11,6 +11,7 @@ class IFMapDependencyManager; class VmInterface; +class SandeshLogicalPort; namespace AGENT { struct LogicalPortKey; @@ -43,6 +44,7 @@ class LogicalPortEntry : AgentRefCount, public AgentDBEntry { bool CopyBase(LogicalPortTable *table, const LogicalPortData *data); virtual bool Copy(LogicalPortTable *table, const LogicalPortData *data) = 0; + virtual void SetSandeshData(SandeshLogicalPort *data) const; void SendObjectLog(AgentLogEvent::type event) const; bool DBEntrySandesh(Sandesh *sresp, std::string &name) const; @@ -136,6 +138,7 @@ class VlanLogicalPortEntry : public LogicalPortEntry { uint16_t vlan() const { return vlan_; } bool Copy(LogicalPortTable *table, const LogicalPortData *data); + void SetSandeshData(SandeshLogicalPort *data) const; private: uint16_t vlan_; diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.cc b/src/vnsw/agent/physical_devices/tables/physical_device.cc index d257dfa30de..9b20973e589 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device.cc @@ -176,9 +176,10 @@ static PhysicalDeviceKey *BuildKey(const autogen::PhysicalRouter *router) { static PhysicalDeviceData *BuildData(const IFMapNode *node, const autogen::PhysicalRouter *router) { boost::system::error_code ec; - IpAddress ip = IpAddress::from_string(router->dataplane_ip(), ec); - IpAddress mip = IpAddress::from_string(router->management_ip(), ec); - assert(!ec); + IpAddress ip = IpAddress(); + IpAddress mip = IpAddress(); + ip = IpAddress::from_string(router->dataplane_ip(), ec); + mip = IpAddress::from_string(router->management_ip(), ec); return new PhysicalDeviceData(node->name(), router->display_name(), router->vendor_name(), ip, mip, "OVS"); } diff --git a/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc b/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc index 5aa45877060..3d73c2384e0 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc @@ -147,7 +147,7 @@ void PhysicalDeviceVnTable::ConfigUpdate(IFMapNode *node) { (node->GetObject()); assert(router); autogen::IdPermsType id_perms = router->id_perms(); - boost::uuids::uuid router_uuid; + boost::uuids::uuid router_uuid = nil_uuid(); CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, router_uuid); diff --git a/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh b/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh index 0a8cc617f75..aa1822e11e4 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh +++ b/src/vnsw/agent/physical_devices/tables/physical_devices.sandesh @@ -77,6 +77,8 @@ struct SandeshLogicalPort { 2: string fq_name; 3: string name; 4: string physical_port; + 5: string vif; + 6: u16 vlan_tag; } response sandesh SandeshLogicalPortListResp { @@ -95,6 +97,8 @@ struct LogicalPortObjectLogInfo { 4: string fq_name; 5: string name; 6: string physical_port; + 7: string vif; + 8: u16 vlan_tag; } objectlog sandesh LogicalPortObjectLog { diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.cc b/src/vnsw/agent/physical_devices/tables/physical_port.cc index f0927f03ebb..31b0728ab01 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_port.cc @@ -140,7 +140,7 @@ static PhysicalPortKey *BuildKey(const autogen::PhysicalInterface *port) { static PhysicalPortData *BuildData(const Agent *agent, IFMapNode *node, const autogen::PhysicalInterface *port) { - boost::uuids::uuid dev_uuid; + boost::uuids::uuid dev_uuid = nil_uuid(); // Find link with physical-router adjacency IFMapNode *adj_node = NULL; adj_node = agent->cfg_listener()->FindAdjacentIFMapNode(agent, node, From f1439988fb092c17bfdd56f9bb043d948b2cdbd9 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sun, 19 Oct 2014 12:36:54 -0700 Subject: [PATCH 005/218] use VN UUID as Logical switch name. since junos donot support colon(:) for logical switch name. Change to remove logical switch name from key of vlan_port_binding. --- .../ovsdb_client/logical_switch_ovsdb.cc | 5 +- .../ovsdb_client/ovsdb_client_idl.cc | 3 + .../ovsdb_client/physical_port_ovsdb.cc | 2 + .../ovsdb_client/vlan_port_binding_ovsdb.cc | 61 +++++++++++++------ .../ovsdb_client/vlan_port_binding_ovsdb.h | 3 +- 5 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index f9f7fc89e33..64f74b5bccd 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -20,9 +20,8 @@ using OVSDB::OvsdbDBObject; LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, const AGENT::PhysicalDeviceVnEntry *entry) : OvsdbDBEntry(table), - mcast_local_row_(NULL), mcast_remote_row_(NULL), - old_mcast_remote_row_(NULL) { - name_ = entry->vn()->GetName(); + name_(UuidToString(entry->vn()->GetUuid())), mcast_local_row_(NULL), + mcast_remote_row_(NULL), old_mcast_remote_row_(NULL) { vxlan_id_ = entry->vn()->GetVxLanId(); device_name_ = entry->device()->name(); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 7fb77b8d288..a73fa39b34e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #if 0 #include #include @@ -70,6 +71,8 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent) : logical_switch_table_.reset(new LogicalSwitchTable(this, (DBTable *)agent->device_manager()->physical_device_vn_table())); physical_port_table_.reset(new PhysicalPortTable(this)); + vlan_port_table_.reset(new VlanPortBindingTable(this, + (DBTable *)agent->device_manager()->logical_port_table())); #if 0 //TODO physical_locator_table_.reset(new PhysicalLocatorTable(this, (DBTable *)agent->nexthop_table())); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc index 70a25299bb9..578d88b60c2 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -59,9 +59,11 @@ void PhysicalPortEntry::Encode(struct ovsdb_idl_txn *txn) { } void PhysicalPortEntry::AddBinding(int16_t vlan, LogicalSwitchEntry *ls) { + binding_table_[vlan] = ls; } void PhysicalPortEntry::DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls) { + binding_table_.erase(vlan); } void PhysicalPortEntry::OverrideOvs() { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index 989642bb2b3..fffbede5d2f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -16,14 +16,18 @@ extern "C" { #include #include +using OVSDB::OvsdbDBEntry; using OVSDB::VlanPortBindingEntry; using OVSDB::VlanPortBindingTable; using OVSDB::PhysicalPortEntry; using OVSDB::LogicalSwitchEntry; VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, - const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_) { - logical_switch_name_ = entry->vm_interface()->vn()->GetName(); + const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_), + logical_switch_name_("") { + if (entry->vm_interface()) + logical_switch_name_ = + UuidToString(entry->vm_interface()->vn()->GetUuid()); physical_port_name_ = entry->physical_port()->name(); vlan_ = entry->vlan(); } @@ -39,26 +43,29 @@ void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) { PhysicalPortTable *p_table = table_->client_idl()->physical_port_table(); PhysicalPortEntry key(p_table, physical_port_name_.c_str()); physical_port_ = p_table->GetReference(&key); - LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); - LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); - logical_switch_ = l_table->GetReference(&ls_key); - PhysicalPortEntry *port = static_cast(physical_port_.get()); - port->AddBinding(vlan_, - static_cast(logical_switch_.get())); + + if (!logical_switch_name_.empty()) { + LogicalSwitchTable *l_table = + table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + logical_switch_ = l_table->GetReference(&ls_key); + port->AddBinding(vlan_, + static_cast(logical_switch_.get())); + } else { + port->DeleteBinding(vlan_, NULL); + } port->Encode(txn); } void VlanPortBindingEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { - if (physical_port_) { - PhysicalPortEntry *port = - static_cast(physical_port_.get()); - port->DeleteBinding(vlan_, - static_cast(logical_switch_.get())); - physical_port_ = NULL; - logical_switch_ = NULL; - } + PhysicalPortEntry *port = + static_cast(physical_port_.get()); + port->DeleteBinding(vlan_, + static_cast(logical_switch_.get())); + logical_switch_ = NULL; + AddMsg(txn); } @@ -76,6 +83,16 @@ void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { } bool VlanPortBindingEntry::Sync(DBEntry *db_entry) { + AGENT::VlanLogicalPortEntry *entry = + static_cast(db_entry); + std::string ls_name(""); + if (entry->vm_interface()) { + ls_name = UuidToString(entry->vm_interface()->vn()->GetUuid()); + } + if (ls_name != logical_switch_name_) { + logical_switch_name_ = ls_name; + return true; + } return false; } @@ -84,10 +101,7 @@ bool VlanPortBindingEntry::IsLess(const KSyncEntry &entry) const { static_cast(entry); if (vlan_ != vps_entry.vlan_) return vlan_ < vps_entry.vlan_; - if (physical_port_name_ != vps_entry.physical_port_name_) - return physical_port_name_ < vps_entry.physical_port_name_; - - return logical_switch_name_ < vps_entry.logical_switch_name_; + return physical_port_name_ < vps_entry.physical_port_name_; } KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { @@ -98,6 +112,9 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { if (!p_port->IsResolved()) { return p_port; } + if (logical_switch_name_.empty()) { + return NULL; + } LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); LogicalSwitchEntry *ls_entry = @@ -133,3 +150,7 @@ KSyncEntry *VlanPortBindingTable::DBToKSyncEntry(const DBEntry* db_entry) { return static_cast(key); } +OvsdbDBEntry *VlanPortBindingTable::AllocOvsEntry(struct ovsdb_idl_row *row) { + return NULL; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h index 851531ab705..6362bb8d79d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h @@ -22,6 +22,7 @@ class VlanPortBindingTable : public OvsdbDBObject { void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row*); KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry* AllocOvsEntry(struct ovsdb_idl_row*); private: DISALLOW_COPY_AND_ASSIGN(VlanPortBindingTable); }; @@ -44,8 +45,8 @@ class VlanPortBindingEntry : public OvsdbDBEntry { friend class VlanPortBindingTable; KSyncEntryPtr logical_switch_; KSyncEntryPtr physical_port_; - std::string physical_port_name_; std::string logical_switch_name_; + std::string physical_port_name_; uint16_t vlan_; DISALLOW_COPY_AND_ASSIGN(VlanPortBindingEntry); }; From 42b9499731cc2b8935a5b0b1927d1f9709fedc18 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Mon, 20 Oct 2014 11:52:58 +0530 Subject: [PATCH 006/218] Support adding l2 routes from OVS clients Move ovs_peer.cc and .h to ovsdb_client/ directory --- .../physical_devices/ovs_tor_agent/SConscript | 1 - .../ovs_tor_agent/ovs_peer.cc | 37 ---------- .../ovs_tor_agent/ovsdb_client/SConscript | 2 + .../ovsdb_client/ovsdb_route_data.cc | 71 ++++++++++++++++++ .../ovsdb_client/ovsdb_route_data.h | 32 ++++++++ .../ovsdb_client/ovsdb_route_peer.cc | 73 +++++++++++++++++++ .../ovsdb_route_peer.h} | 17 +++-- .../ovs_tor_agent/tor_agent_init.cc | 4 +- 8 files changed, 192 insertions(+), 45 deletions(-) delete mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc rename src/vnsw/agent/physical_devices/ovs_tor_agent/{ovs_peer.h => ovsdb_client/ovsdb_route_peer.h} (58%) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript index 3ebc6a1934c..ca013219c5c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript @@ -38,7 +38,6 @@ env.AppendUnique(CCFLAGS='-Wno-return-type') tor_agent = env.Program(target = 'tor_agent', source = [ 'buildinfo.cc', - 'ovs_peer.cc', 'tor_agent_param.cc', 'tor_agent_init.cc', 'main.cc', diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.cc deleted file mode 100644 index 9f0b94c0cec..00000000000 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. - */ -#include - -OvsPeer::OvsPeer(const IpAddress &peer_ip, uint64_t gen_id) : - Peer(Peer::OVS_PEER, "OVS-" + peer_ip.to_string()), peer_ip_(peer_ip), - gen_id_(gen_id) { -} - -OvsPeer::~OvsPeer() { -} - -bool OvsPeer::Compare(const Peer *rhs) const { - const OvsPeer *rhs_peer = static_cast(rhs); - if (gen_id_ != rhs_peer->gen_id_) - return gen_id_ < rhs_peer->gen_id_; - - return peer_ip_ < rhs_peer->peer_ip_; -} - -OvsPeerManager::OvsPeerManager() : gen_id_(0) { -} - -OvsPeerManager::~OvsPeerManager() { - assert(table_.size() == 0); -} - -OvsPeer *OvsPeerManager::Allocate(const IpAddress &peer_ip) { - OvsPeer *peer = new OvsPeer(peer_ip, gen_id_++); - table_.insert(peer); -} - -void OvsPeerManager::Free(OvsPeer *peer) { - table_.erase(peer); - delete peer; -} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index 4af500b85fa..24cec7fa00a 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -28,6 +28,8 @@ libovsdbclient = env.Library('ovsdbclient', 'ovsdb_client_tcp.cc', 'ovsdb_entry.cc', 'ovsdb_object.cc', + 'ovsdb_route_data.cc', + 'ovsdb_route_peer.cc', 'physical_switch_ovsdb.cc', 'logical_switch_ovsdb.cc', 'physical_port_ovsdb.cc', diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc new file mode 100644 index 00000000000..be4e626d766 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace boost::asio; + +OvsdbRouteData::OvsdbRouteData(const Peer *peer, uint32_t vxlan_id, + const Ip4Address &tor_ip, + const Ip4Address &router_id, + const std::string &tor_vrf, + const std::string &dest_vn_name) : + AgentRouteData(false), peer_(peer), vxlan_id_(vxlan_id), tor_ip_(tor_ip), + tor_vrf_(tor_vrf), router_id_(router_id), dest_vn_name_(dest_vn_name) { +} + +OvsdbRouteData::~OvsdbRouteData() { +} + +std::string OvsdbRouteData::ToString() const { + return "OVS Route Data"; +} + +bool OvsdbRouteData::AddChangePath(Agent *agent, AgentPath *path) { + bool ret = false; + NextHop *nh = NULL; + + if (path->vxlan_id() != vxlan_id_) { + path->set_vxlan_id(vxlan_id_); + ret = true; + } + + if (path->dest_vn_name() != dest_vn_name_) { + path->set_dest_vn_name(dest_vn_name_); + ret = true; + } + + SecurityGroupList sg_list; + if (path->sg_list() != sg_list) { + path->set_sg_list(sg_list); + ret = true; + } + + // Create Tunnel-NH first + TunnelType::Type type = TunnelType::ComputeType(TunnelType::VxlanType()); + DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); + nh_req.key.reset(new TunnelNHKey(tor_vrf_, router_id_, tor_ip_, false, + type)); + nh_req.data.reset(new TunnelNHData()); + agent->nexthop_table()->Process(nh_req); + + // Get the NH + TunnelNHKey key(tor_vrf_, router_id_, tor_ip_, false, type); + nh = static_cast(agent->nexthop_table()->FindActiveEntry(&key)); + + path->set_unresolved(false); + if (path->ChangeNH(agent, nh) == true) + ret = true; + + return ret; +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h new file mode 100644 index 00000000000..9e9fafd6302 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_ROUTE_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_ROUTE_H_ + +#include +#include + +class Peer; + +class OvsdbRouteData : public AgentRouteData { +public: + OvsdbRouteData(const Peer *peer, uint32_t vxlan_id, + const Ip4Address &tor_ip, const Ip4Address &router_id, + const std::string &tor_vrf, const std::string &dest_vn_name); + virtual ~OvsdbRouteData(); + + virtual std::string ToString() const; + virtual bool AddChangePath(Agent *agent, AgentPath *path); + +private: + const Peer *peer_; + uint32_t vxlan_id_; + Ip4Address tor_ip_; + std::string tor_vrf_; + Ip4Address router_id_; + std::string dest_vn_name_; + DISALLOW_COPY_AND_ASSIGN(OvsdbRouteData); +}; + +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_ROUTE_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc new file mode 100644 index 00000000000..43303d5f91d --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ +#include +#include + +OvsPeer::OvsPeer(const IpAddress &peer_ip, uint64_t gen_id, + OvsPeerManager *peer_manager) : + Peer(Peer::OVS_PEER, "OVS-" + peer_ip.to_string()), peer_ip_(peer_ip), + gen_id_(gen_id), peer_manager_(peer_manager) { +} + +OvsPeer::~OvsPeer() { +} + +bool OvsPeer::Compare(const Peer *rhs) const { + const OvsPeer *rhs_peer = static_cast(rhs); + if (gen_id_ != rhs_peer->gen_id_) + return gen_id_ < rhs_peer->gen_id_; + + return peer_ip_ < rhs_peer->peer_ip_; +} + +bool OvsPeer::AddOvsRoute(const boost::uuids::uuid &vn_uuid, + const MacAddress &mac, Ip4Address &tor_ip) { + + Agent *agent = peer_manager_->agent(); + + // We dont learn the MAC to IP binding in case of TOR. Populate 0.0.0.0 + // (unknown ip) for the MAC in EVPN route + Ip4Address prefix_ip = Ip4Address::from_string("0.0.0.0"); + int prefix_len = 32; + + VnEntry *vn = agent->vn_table()->Find(vn_uuid); + if (vn == NULL) + return false; + + VrfEntry *vrf = vn->GetVrf(); + if (vrf == NULL) + return false; + + OvsdbRouteData *data = new OvsdbRouteData(this, vn->vxlan_id()->vxlan_id(), + tor_ip, agent->router_id(), + agent->fabric_vrf_name(), + vn->GetName()); + Layer2AgentRouteTable *table = static_cast + (vrf->GetLayer2RouteTable()); + table->AddRemoteVmRouteReq(this, vrf->GetName(), mac, prefix_ip, + vn->vxlan_id()->vxlan_id(), prefix_len, data); + return true; +} + +OvsPeerManager::OvsPeerManager(Agent *agent) : gen_id_(0), agent_(agent) { +} + +OvsPeerManager::~OvsPeerManager() { + assert(table_.size() == 0); +} + +OvsPeer *OvsPeerManager::Allocate(const IpAddress &peer_ip) { + OvsPeer *peer = new OvsPeer(peer_ip, gen_id_++, this); + table_.insert(peer); + return peer; +} + +void OvsPeerManager::Free(OvsPeer *peer) { + table_.erase(peer); + delete peer; +} + +Agent *OvsPeerManager::agent() const { + return agent_; +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h similarity index 58% rename from src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.h rename to src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h index aca02eefaf9..00e5113da22 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovs_peer.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h @@ -1,22 +1,27 @@ /* * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ -#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVS_PEER_H_ -#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVS_PEER_H_ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_PEER_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_PEER_H_ #include #include +class OvsPeerManager; + // Peer for routes added by OVS class OvsPeer : public Peer { public: - OvsPeer(const IpAddress &peer_ip, uint64_t gen_id); + OvsPeer(const IpAddress &peer_ip, uint64_t gen_id, OvsPeerManager *manager); virtual ~OvsPeer(); bool Compare(const Peer *rhs) const; + bool AddOvsRoute(const boost::uuids::uuid &vn_uuid, const MacAddress &mac, + Ip4Address &tor_ip); private: IpAddress peer_ip_; uint64_t gen_id_; + OvsPeerManager *peer_manager_; DISALLOW_COPY_AND_ASSIGN(OvsPeer); }; @@ -29,16 +34,18 @@ class OvsPeerManager { }; typedef std::set OvsPeerTable; - OvsPeerManager(); + OvsPeerManager(Agent *agent); virtual ~OvsPeerManager(); OvsPeer *Allocate(const IpAddress &peer_ip); void Free(OvsPeer *peer); + Agent *agent() const; private: uint64_t gen_id_; + Agent *agent_; OvsPeerTable table_; DISALLOW_COPY_AND_ASSIGN(OvsPeerManager); }; -#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVS_PEER_H_ +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVS_PEER_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc index feb5980f53f..7ce125607ae 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -74,7 +74,7 @@ void TorAgentInit::FactoryInit() { } void TorAgentInit::CreatePeers() { - ovs_peer_manager_.reset(new OvsPeerManager()); + ovs_peer_manager_.reset(new OvsPeerManager(agent())); } void TorAgentInit::CreateModules() { From 327936d4a5c773ed272544c8bc555c832d3395c6 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sun, 19 Oct 2014 23:50:22 -0700 Subject: [PATCH 007/218] adding introspect trace support for ovsdb --- .../physical_devices/ovs_tor_agent/main.cc | 1 + .../ovsdb_client/logical_switch_ovsdb.cc | 54 ++++++++++++------- .../ovsdb_client/logical_switch_ovsdb.h | 8 +++ .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 28 ++++++++++ .../ovsdb_client/ovsdb_client_idl.cc | 2 + .../ovsdb_client/ovsdb_client_idl.h | 5 ++ .../ovsdb_client/physical_switch_ovsdb.cc | 30 +++++++---- .../ovsdb_client/physical_switch_ovsdb.h | 6 ++- 8 files changed, 105 insertions(+), 29 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/main.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/main.cc index 999826da857..f1751d9c431 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/main.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/main.cc @@ -62,6 +62,7 @@ int main(int argc, char *argv[]) { MiscUtils::LogVersionInfo(build_info, Category::VROUTER); init.set_agent_param(¶ms); + agent->set_agent_init(&init); // Read agent parameters from config file and arguments init.ProcessOptions(init_file, argv[0]); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index 64f74b5bccd..0be94b6e168 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include using namespace AGENT; using OVSDB::LogicalSwitchEntry; @@ -55,6 +56,7 @@ void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) { if (old_mcast_remote_row_ != NULL) { ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); } + SendTrace(LogicalSwitchEntry::ADD_REQ); } void LogicalSwitchEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { @@ -72,6 +74,7 @@ void LogicalSwitchEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); } ovsdb_wrapper_delete_logical_switch(ovs_entry_); + SendTrace(LogicalSwitchEntry::DEL_REQ); } void LogicalSwitchEntry::OvsdbChange() { @@ -110,6 +113,30 @@ KSyncEntry *LogicalSwitchEntry::UnresolvedReference() { return NULL; } +void LogicalSwitchEntry::SendTrace(Trace event) const { + SandeshLogicalSwitchInfo info; + switch (event) { + case ADD_REQ: + info.set_op("Add Requested"); + break; + case DEL_REQ: + info.set_op("Delete Requested"); + break; + case ADD_ACK: + info.set_op("Add Received"); + break; + case DEL_ACK: + info.set_op("Delete Received"); + break; + default: + info.set_op("unknown"); + } + info.set_name(name_); + info.set_device_name(device_name_); + info.set_vxlan(vxlan_id_); + OVSDB_TRACE(LogicalSwitch, info); +} + LogicalSwitchTable::LogicalSwitchTable(OvsdbClientIdl *idl, DBTable *table) : OvsdbDBObject(idl, table) { idl->Register(OvsdbClientIdl::OVSDB_LOGICAL_SWITCH, @@ -130,18 +157,18 @@ LogicalSwitchTable::~LogicalSwitchTable() { void LogicalSwitchTable::OvsdbNotify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { + const char *name = ovsdb_wrapper_logical_switch_name(row); + int64_t vxlan = ovsdb_wrapper_logical_switch_tunnel_key(row); if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Logical Switch %s, VxLAN %ld\n", - ovsdb_wrapper_logical_switch_name(row), - ovsdb_wrapper_logical_switch_tunnel_key(row)); - LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + LogicalSwitchEntry key(this, name); NotifyDeleteOvsdb((OvsdbDBEntry*)&key); + key.vxlan_id_ = vxlan; + key.SendTrace(LogicalSwitchEntry::DEL_ACK); } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of Logical Switch %s, Vxlan %ld\n", - ovsdb_wrapper_logical_switch_name(row), - ovsdb_wrapper_logical_switch_tunnel_key(row)); - LogicalSwitchEntry key(this, ovsdb_wrapper_logical_switch_name(row)); + LogicalSwitchEntry key(this, name); NotifyAddOvsdb((OvsdbDBEntry*)&key, row); + key.vxlan_id_ = vxlan; + key.SendTrace(LogicalSwitchEntry::ADD_ACK); } else { assert(0); } @@ -205,17 +232,6 @@ void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, } else { assert(0); } - if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Logical Switch %s, VxLAN %ld\n", - ovsdb_wrapper_logical_switch_name(row), - ovsdb_wrapper_logical_switch_tunnel_key(row)); - } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of Logical Switch %s, Vxlan %ld\n", - ovsdb_wrapper_logical_switch_name(row), - ovsdb_wrapper_logical_switch_tunnel_key(row)); - } else { - assert(0); - } } KSyncEntry *LogicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h index 3bb0709af08..6a3f93ea749 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h @@ -32,6 +32,12 @@ class LogicalSwitchTable : public OvsdbDBObject { class LogicalSwitchEntry : public OvsdbDBEntry { public: + enum Trace { + ADD_REQ, + DEL_REQ, + ADD_ACK, + DEL_ACK, + }; LogicalSwitchEntry(OvsdbDBObject *table, const char *name) : OvsdbDBEntry(table), name_(name) {} LogicalSwitchEntry(OvsdbDBObject *table, const LogicalSwitchEntry *key); @@ -51,6 +57,8 @@ class LogicalSwitchEntry : public OvsdbDBEntry { std::string ToString() const {return "Logical Switch";} KSyncEntry* UnresolvedReference(); private: + void SendTrace(Trace event) const; + friend class LogicalSwitchTable; std::string name_; std::string device_name_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index 3f7f4efde8c..bdccb9914e6 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -25,3 +25,31 @@ response sandesh OvsdbClientResp { request sandesh OvsdbClientReq { } +/**************************************************************************** + Sandesh definitions for Physical Switch. + ****************************************************************************/ + +struct SandeshPhysicalSwitchInfo { + 1: string op; + 2: string name; +} + +traceobject sandesh OvsdbPhysicalSwitch { + 1: SandeshPhysicalSwitchInfo p_switch; +} + +/**************************************************************************** + Sandesh definitions for Logical Switch. + ****************************************************************************/ + +struct SandeshLogicalSwitchInfo { + 1: string op; + 2: string name; + 3: u64 vxlan; + 4: string device_name; +} + +traceobject sandesh OvsdbLogicalSwitch { + 1: SandeshLogicalSwitchInfo l_switch; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index a73fa39b34e..d549b8ee61d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -23,6 +23,8 @@ extern "C" { #include +SandeshTraceBufferPtr OvsdbTraceBuf(SandeshTraceBufferCreate("Ovsdb", 5000)); + namespace AGENT { class PhysicalDeviceTable; class PhysicalPortTable; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index ed6d5bf421f..4314f777a3a 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -11,6 +11,11 @@ #include #include +extern SandeshTraceBufferPtr OvsdbTraceBuf; +#define OVSDB_TRACE(obj, ...)\ +do {\ + Ovsdb##obj::TraceMsg(OvsdbTraceBuf, __FILE__, __LINE__, __VA_ARGS__);\ +} while(false); namespace OVSDB { class OvsdbClientSession; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc index bb7f44a608b..209039f8e39 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -7,6 +7,7 @@ extern "C" { }; #include #include +#include using OVSDB::PhysicalSwitchEntry; using OVSDB::PhysicalSwitchTable; @@ -21,13 +22,24 @@ PhysicalSwitchEntry::~PhysicalSwitchEntry() { bool PhysicalSwitchEntry::IsLess(const KSyncEntry &entry) const { const PhysicalSwitchEntry &ps_entry = static_cast(entry); - return (name_.compare(ps_entry.name_) < 0); + return (name_ < ps_entry.name_); } KSyncEntry *PhysicalSwitchEntry::UnresolvedReference() { return NULL; } +void PhysicalSwitchEntry::SendTrace(Trace event) const { + SandeshPhysicalSwitchInfo info; + if (event == ADD) { + info.set_op("Add"); + } else { + info.set_op("Delete"); + } + info.set_name(name_); + OVSDB_TRACE(PhysicalSwitch, info); +} + PhysicalSwitchTable::PhysicalSwitchTable(OvsdbClientIdl *idl) : OvsdbObject(idl) { idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH, @@ -40,22 +52,22 @@ PhysicalSwitchTable::~PhysicalSwitchTable() { void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { + const char *name = ovsdb_wrapper_physical_switch_name(row); if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Physical Switch %s\n", - ovsdb_wrapper_physical_switch_name(row)); - PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, name); PhysicalSwitchEntry *entry = static_cast(Find(&key)); - if (entry != NULL) + if (entry != NULL) { + entry->SendTrace(PhysicalSwitchEntry::DEL); Delete(entry); + } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of Physical Switch %s\n", - ovsdb_wrapper_physical_switch_name(row)); - PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry key(this, name); PhysicalSwitchEntry *entry = static_cast(Find(&key)); if (entry == NULL) { - Create(&key); + entry = static_cast(Create(&key)); + entry->SendTrace(PhysicalSwitchEntry::ADD); } } else { assert(0); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h index 50ecf5e7b71..4445b779f03 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h @@ -22,6 +22,10 @@ class PhysicalSwitchTable : public OvsdbObject { class PhysicalSwitchEntry : public OvsdbEntry { public: + enum Trace { + ADD, + DEL, + }; PhysicalSwitchEntry(PhysicalSwitchTable *table, const std::string &name); ~PhysicalSwitchEntry(); @@ -29,7 +33,7 @@ class PhysicalSwitchEntry : public OvsdbEntry { std::string ToString() const {return "Physical Switch";} KSyncEntry* UnresolvedReference(); private: - PhysicalSwitchEntry(PhysicalSwitchTable *table, const PhysicalSwitchEntry *key); + void SendTrace(Trace event) const; friend class PhysicalSwitchTable; std::string name_; From 8978379e1129d7750f6373a0c75a6f61955ea026 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 20 Oct 2014 02:25:50 -0700 Subject: [PATCH 008/218] Changes to create ovs peer And add routes for export to bgp. --- .../ovs_tor_agent/ovsdb_client/SConscript | 2 +- .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 8 ++ .../ovsdb_client/ovsdb_client.cc | 5 +- .../ovs_tor_agent/ovsdb_client/ovsdb_client.h | 9 +- .../ovsdb_client/ovsdb_client_idl.cc | 16 ++-- .../ovsdb_client/ovsdb_client_idl.h | 14 ++- .../ovsdb_client/ovsdb_client_tcp.cc | 17 ++-- .../ovsdb_client/ovsdb_client_tcp.h | 7 +- .../ovsdb_client/ovsdb_wrapper.c | 11 +++ .../ovsdb_client/ovsdb_wrapper.h | 4 +- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 85 ++++++++----------- .../ovsdb_client/unicast_mac_local_ovsdb.h | 41 +++------ .../ovs_tor_agent/tor_agent_init.cc | 3 +- 13 files changed, 118 insertions(+), 104 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index 24cec7fa00a..5332123c1b3 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -35,6 +35,6 @@ libovsdbclient = env.Library('ovsdbclient', 'physical_port_ovsdb.cc', 'vlan_port_binding_ovsdb.cc', # 'physical_locator_ovsdb.cc', - # 'unicast_mac_local_ovsdb.cc', + 'unicast_mac_local_ovsdb.cc', ]) env.Requires(libovsdbclient, '#/build/include/openvswitch/include') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index bdccb9914e6..966d41650f8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -25,6 +25,14 @@ response sandesh OvsdbClientResp { request sandesh OvsdbClientReq { } +traceobject sandesh OvsdbTrace { + 1: string log; +} + +traceobject sandesh OvsdbError { + 1: string error; +} + /**************************************************************************** Sandesh definitions for Physical Switch. ****************************************************************************/ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc index 5e02b189e4a..cd50defcf7f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc @@ -14,8 +14,9 @@ using OVSDB::OvsdbClient; void OvsdbClient::Init() { } -OvsdbClient *OvsdbClient::Allocate(Agent *agent, TorAgentParam *params) { - return (new OvsdbClientTcp(agent, params)); +OvsdbClient *OvsdbClient::Allocate(Agent *agent, TorAgentParam *params, + OvsPeerManager *manager) { + return (new OvsdbClientTcp(agent, params, manager)); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h index e51f171e63f..2ecc07b074c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h @@ -8,10 +8,12 @@ class TorAgentParam; class SandeshOvsdbClient; +class OvsPeerManager; + namespace OVSDB { class OvsdbClient { public: - OvsdbClient() {} + OvsdbClient(OvsPeerManager *manager) : peer_manager_(manager) {} virtual ~OvsdbClient() {} virtual void RegisterClients() = 0; virtual const std::string protocol() = 0; @@ -20,7 +22,10 @@ class OvsdbClient { virtual Ip4Address tsn_ip() = 0; virtual void AddSessionInfo(SandeshOvsdbClient &client) = 0; void Init(); - static OvsdbClient* Allocate(Agent *agent, TorAgentParam *params); + static OvsdbClient* Allocate(Agent *agent, TorAgentParam *params, + OvsPeerManager *manager); +protected: + OvsPeerManager *peer_manager_; private: DISALLOW_COPY_AND_ASSIGN(OvsdbClient); }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index d549b8ee61d..0b4f22e818b 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -10,15 +10,18 @@ extern "C" { #include }; +#include +#include #include +#include #include #include #include #include #include +#include #if 0 #include -#include #endif #include @@ -53,15 +56,16 @@ void ovsdb_wrapper_idl_txn_ack(void *idl_base, struct ovsdb_idl_txn *txn) { bool success = ovsdb_wrapper_is_txn_success(txn); client_idl->DeleteTxn(txn); if (!success) { - printf("Transaction failed\n"); + OVSDB_TRACE(Error, "Transaction failed"); } if (entry) entry->Ack(success); } }; -OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent) : - idl_(ovsdb_wrapper_idl_create()), session_(session), pending_txn_() { +OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, + OvsPeerManager *manager) : idl_(ovsdb_wrapper_idl_create()), + session_(session), pending_txn_() { vtep_global_= ovsdb_wrapper_vteprec_global_first(idl_); ovsdb_wrapper_idl_set_callback(idl_, (void *)this, ovsdb_wrapper_idl_callback, ovsdb_wrapper_idl_txn_ack); @@ -69,16 +73,18 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent) : for (int i = 0; i < OVSDB_TYPE_COUNT; i++) { callback_[i] = NULL; } + route_peer_.reset(manager->Allocate(IpAddress())); physical_switch_table_.reset(new PhysicalSwitchTable(this)); logical_switch_table_.reset(new LogicalSwitchTable(this, (DBTable *)agent->device_manager()->physical_device_vn_table())); physical_port_table_.reset(new PhysicalPortTable(this)); vlan_port_table_.reset(new VlanPortBindingTable(this, (DBTable *)agent->device_manager()->logical_port_table())); + unicast_mac_local_ovsdb_.reset(new UnicastMacLocalOvsdb(this, + route_peer())); #if 0 //TODO physical_locator_table_.reset(new PhysicalLocatorTable(this, (DBTable *)agent->nexthop_table())); - unicast_mac_local_table_.reset(new UnicastMacLocalTable(this)); #endif } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 4314f777a3a..1c8cef6a482 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -17,6 +17,9 @@ do {\ Ovsdb##obj::TraceMsg(OvsdbTraceBuf, __FILE__, __LINE__, __VA_ARGS__);\ } while(false); +class OvsPeer; +class OvsPeerManager; + namespace OVSDB { class OvsdbClientSession; class PhysicalSwitchTable; @@ -24,7 +27,7 @@ class LogicalSwitchTable; class PhysicalPortTable; class VlanPortBindingTable; class PhysicalLocatorTable; -class UnicastMacLocalTable; +class UnicastMacLocalOvsdb; class OvsdbEntryBase; class OvsdbClientIdl { @@ -50,7 +53,7 @@ class OvsdbClientIdl { typedef boost::function NotifyCB; typedef std::map PendingTxnMap; - OvsdbClientIdl(OvsdbClientSession *session, Agent *agent); + OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, OvsPeerManager *manager); virtual ~OvsdbClientIdl(); // Send request to start monitoring OVSDB server @@ -68,6 +71,7 @@ class OvsdbClientIdl { // Get TOR Service Node IP Ip4Address tsn_ip(); + OvsPeer *route_peer() {return route_peer_.get();} PhysicalSwitchTable *physical_switch_table() {return physical_switch_table_.get();} LogicalSwitchTable *logical_switch_table() {return logical_switch_table_.get();} PhysicalPortTable *physical_port_table() {return physical_port_table_.get();} @@ -84,20 +88,22 @@ class OvsdbClientIdl { OvsdbClientSession *session_; NotifyCB callback_[OVSDB_TYPE_COUNT]; PendingTxnMap pending_txn_; + std::auto_ptr route_peer_; std::auto_ptr physical_switch_table_; std::auto_ptr logical_switch_table_; std::auto_ptr physical_port_table_; std::auto_ptr vlan_port_table_; + std::auto_ptr unicast_mac_local_ovsdb_; #if 0 //TODO std::auto_ptr physical_locator_table_; - std::auto_ptr unicast_mac_local_table_; #endif DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl); }; class OvsdbClientSession { public: - OvsdbClientSession(Agent *agent) : client_idl_(this, agent), agent_(agent) {} + OvsdbClientSession(Agent *agent, OvsPeerManager *manager) : + client_idl_(this, agent, manager), agent_(agent) {} virtual ~OvsdbClientSession() {} virtual Ip4Address tsn_ip() = 0; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc index 75708982cbb..0412d4e8a33 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -14,10 +14,11 @@ using OVSDB::OvsdbClientTcp; using OVSDB::OvsdbClientTcpSession; using OVSDB::OvsdbClientTcpSessionReader; -OvsdbClientTcp::OvsdbClientTcp(Agent *agent, TorAgentParam *params) : - TcpServer(agent->event_manager()), agent_(agent), session_(NULL), - server_ep_(IpAddress(params->tor_ip()), params->tor_port()), - tsn_ip_(params->tsn_ip()) { +OvsdbClientTcp::OvsdbClientTcp(Agent *agent, TorAgentParam *params, + OvsPeerManager *manager) : TcpServer(agent->event_manager()), + OvsdbClient(manager), agent_(agent), session_(NULL), + server_ep_(IpAddress(params->tor_ip()), params->tor_port()), + tsn_ip_(params->tsn_ip()) { } OvsdbClientTcp::~OvsdbClientTcp() { @@ -29,7 +30,8 @@ void OvsdbClientTcp::RegisterClients() { } TcpSession *OvsdbClientTcp::AllocSession(Socket *socket) { - TcpSession *session = new OvsdbClientTcpSession(agent_, this, socket); + TcpSession *session = new OvsdbClientTcpSession(agent_, peer_manager_, + this, socket); session->set_observer(boost::bind(&OvsdbClientTcp::OnSessionEvent, this, _1, _2)); return session; @@ -82,8 +84,9 @@ void OvsdbClientTcp::AddSessionInfo(SandeshOvsdbClient &client){ client.set_sessions(session_list); } -OvsdbClientTcpSession::OvsdbClientTcpSession(Agent *agent, TcpServer *server, - Socket *sock, bool async_ready) : OvsdbClientSession(agent), +OvsdbClientTcpSession::OvsdbClientTcpSession(Agent *agent, + OvsPeerManager *manager, TcpServer *server, Socket *sock, + bool async_ready) : OvsdbClientSession(agent, manager), TcpSession(server, sock, async_ready), status_("Init") { reader_ = new OvsdbClientTcpSessionReader(this, boost::bind(&OvsdbClientTcpSession::RecvMsg, this, _1, _2)); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h index d4b7e931a92..759ddd08a1b 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -44,8 +44,8 @@ class OvsdbClientTcpSession : public OvsdbClientSession, public TcpSession { u_int8_t *buf; std::size_t len; }; - OvsdbClientTcpSession(Agent *agent, TcpServer *server, Socket *sock, - bool async_ready = true); + OvsdbClientTcpSession(Agent *agent, OvsPeerManager *manager, + TcpServer *server, Socket *sock, bool async_ready = true); ~OvsdbClientTcpSession(); // Send message to OVSDB server @@ -71,7 +71,8 @@ class OvsdbClientTcpSession : public OvsdbClientSession, public TcpSession { class OvsdbClientTcp : public TcpServer, public OvsdbClient { public: - OvsdbClientTcp(Agent *agent, TorAgentParam *params); + OvsdbClientTcp(Agent *agent, TorAgentParam *params, + OvsPeerManager *manager); virtual ~OvsdbClientTcp(); virtual TcpSession *AllocSession(Socket *socket); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index 780495d7085..a91de4c60d7 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -337,6 +337,17 @@ ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row) return NULL; } +char * +ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_local *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; + if (mac->locator) { + return mac->locator->dst_ip; + } + return NULL; +} + /* multicast mac local */ void ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index 9823334c7d2..bfc642a728e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -69,8 +69,8 @@ void ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *); /* unicast mac local */ char *ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row); char *ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row); -char * -ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row); /* unicast mac remote */ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index cee5ccc3fb9..934a9c7ef9e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -3,71 +3,56 @@ */ extern "C" { -#include +#include }; +#include +#include +#include +#include +#include #include -UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalTable *table, - struct ovsdb_idl_row *ovsdb_row, std::string mac, std::string ip_addr, - std::string ls_name) : OvsdbEntry(table), - ovsdb_row_(ovsdb_row), mac_(mac), ip_addr_(ip_addr), ls_name_(ls_name) { -} - -bool UnicastMacLocalEntry::IsLess(const KSyncEntry &entry) const { - const UnicastMacLocalEntry &uc_entry = - static_cast(entry); - return (ovsdb_row_ < uc_entry.ovsdb_row_); -} - -KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() { - return NULL; -} +using OVSDB::UnicastMacLocalOvsdb; +using std::string; -UnicastMacLocalTable::UnicastMacLocalTable(OvsdbClientIdl *idl) : - OvsdbObject(idl) { - idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, - boost::bind(&UnicastMacLocalTable::Notify, this, _1, _2)); +UnicastMacLocalOvsdb::UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer) : + client_idl_(idl), peer_(peer) { + client_idl_->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, + boost::bind(&UnicastMacLocalOvsdb::Notify, this, _1, _2)); } -UnicastMacLocalTable::~UnicastMacLocalTable() { +UnicastMacLocalOvsdb::~UnicastMacLocalOvsdb() { client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL); } -void UnicastMacLocalTable::Notify(OvsdbClientIdl::Op op, +void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { - /* if logical switch is not avialable, trigger entry delete */ - bool delete_entry = - (ovsdb_wrapper_ucast_mac_local_logical_switch(row) == NULL); const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row); - if (ls_name == NULL) - ls_name = ""; - UnicastMacLocalEntry key(this, row, ovsdb_wrapper_ucast_mac_local_mac(row), - ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); - UnicastMacLocalEntry *entry = - static_cast(Find(&key)); + const char *mac_str = ovsdb_wrapper_ucast_mac_local_mac(row); + const char *dest_ip = ovsdb_wrapper_ucast_mac_local_dst_ip(row); + /* ignore if ls_name is not present */ + if (ls_name == NULL) { + return; + } + boost::uuids::uuid ls_uuid = StringToUuid(ls_name); + MacAddress mac(mac_str); + Ip4Address dest; + /* trigger delete if dest ip is not available */ + bool delete_entry = true; + if (dest_ip != NULL) { + delete_entry = false; + boost::system::error_code err; + dest = Ip4Address::from_string(dest_ip, err); + } if (op == OvsdbClientIdl::OVSDB_DEL || delete_entry) { - printf("Delete of unicast local mac %s, IP %s, Logical Switch %s\n", - ovsdb_wrapper_ucast_mac_local_mac(row), - ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); - if (entry != NULL) - Delete(entry); + //TODO delete function not available in ovs peer } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of unicast local mac %s, IP %s, Logical Switch %s\n", - ovsdb_wrapper_ucast_mac_local_mac(row), - ovsdb_wrapper_ucast_mac_local_ip(row), ls_name); - if (entry == NULL) - Create(&key); + OVSDB_TRACE(Trace, string("Adding Route ") + string(mac_str) + + string(" VN uuid ") + string(ls_name) + + string(" destination IP ") + string(dest_ip)); + peer_->AddOvsRoute(ls_uuid, mac, dest); } else { assert(0); } } -KSyncEntry *UnicastMacLocalTable::Alloc(const KSyncEntry *key, uint32_t index) { - const UnicastMacLocalEntry *k_entry = - static_cast(key); - UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, - k_entry->ovsdb_row_, k_entry->mac_, k_entry->ip_addr_, - k_entry->ls_name_); - return entry; -} - diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h index b281ecadc67..f49126e0fad 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h @@ -2,39 +2,26 @@ * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ -#ifndef __UNICAST_MAC_LOCAL_OVSDB_H__ -#define __UNICAST_MAC_LOCAL_OVSDB_H__ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ -#include +#include +class OvsPeer; -class UnicastMacLocalTable : public OvsdbObject { +namespace OVSDB { +class UnicastMacLocalOvsdb { public: - UnicastMacLocalTable(OvsdbClientIdl *idl); - virtual ~UnicastMacLocalTable(); + UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer); + ~UnicastMacLocalOvsdb(); - void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); - KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); -private: - DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalTable); -}; + void Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row); -class UnicastMacLocalEntry : public OvsdbEntry { -public: - UnicastMacLocalEntry(UnicastMacLocalTable *table, - struct ovsdb_idl_row *ovsdb_row, std::string mac, - std::string ip_addr, std::string ls_name); - - bool IsLess(const KSyncEntry&) const; - std::string ToString() const {return "Unicast Mac Local";} - KSyncEntry* UnresolvedReference(); private: - friend class UnicastMacLocalTable; - struct ovsdb_idl_row *ovsdb_row_; - std::string mac_; - std::string ip_addr_; - std::string ls_name_; - UnicastMacLocalTable *table_; + OvsdbClientIdl *client_idl_; + OvsPeer *peer_; + DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalOvsdb); +}; }; -#endif //__UNICAST_MAC_LOCAL_OVSDB_H__ +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc index 7ce125607ae..e6a2d11d709 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc @@ -81,7 +81,8 @@ void TorAgentInit::CreateModules() { device_manager_.reset(new PhysicalDeviceManager(agent())); agent()->set_device_manager(device_manager_.get()); ovsdb_client_.reset(OvsdbClient::Allocate(agent(), - static_cast(agent_param()))); + static_cast(agent_param()), + ovs_peer_manager())); } void TorAgentInit::CreateDBTables() { From ab696a9d9a0519fd0b202c2e80aa62c2f5be1750 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 20 Oct 2014 03:31:06 -0700 Subject: [PATCH 009/218] fix for reoute export to bgp. --- src/vnsw/agent/oper/agent_route.cc | 3 ++- .../ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index a1260e4ff59..f821d3798a6 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -522,7 +522,8 @@ AgentPath *AgentRoute::FindLocalVmPortPath() const { } if (path->peer()->GetType() == Peer::ECMP_PEER || path->peer()->GetType() == Peer::VGW_PEER || - path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) { + path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER || + path->peer()->GetType() == Peer::OVS_PEER) { return const_cast(path); } } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc index be4e626d766..d50fd99c01d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc @@ -63,6 +63,9 @@ bool OvsdbRouteData::AddChangePath(Agent *agent, AgentPath *path) { TunnelNHKey key(tor_vrf_, router_id_, tor_ip_, false, type); nh = static_cast(agent->nexthop_table()->FindActiveEntry(&key)); + path->set_tunnel_bmap(TunnelType::VxlanType()); + path->set_tunnel_type(TunnelType::ComputeType(path->tunnel_bmap())); + path->set_unresolved(false); if (path->ChangeNH(agent, nh) == true) ret = true; From f2d3a7c6c2258bdad8bd3a351bad1eb215710879 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 20 Oct 2014 06:00:34 -0700 Subject: [PATCH 010/218] Support for unicast remote mac in ovsdb. --- .../ovs_tor_agent/ovsdb_client/SConscript | 1 + .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 15 ++ .../ovsdb_client/ovsdb_wrapper.c | 79 ++++++- .../ovsdb_client/ovsdb_wrapper.h | 7 + .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 192 +++++++++++------- .../ovsdb_client/unicast_mac_remote_ovsdb.h | 47 +++-- 6 files changed, 242 insertions(+), 99 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index 5332123c1b3..cc5da7562c8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -36,5 +36,6 @@ libovsdbclient = env.Library('ovsdbclient', 'vlan_port_binding_ovsdb.cc', # 'physical_locator_ovsdb.cc', 'unicast_mac_local_ovsdb.cc', + 'unicast_mac_remote_ovsdb.cc', ]) env.Requires(libovsdbclient, '#/build/include/openvswitch/include') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index 966d41650f8..faa06f32103 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -61,3 +61,18 @@ traceobject sandesh OvsdbLogicalSwitch { 1: SandeshLogicalSwitchInfo l_switch; } +/**************************************************************************** + Sandesh definitions for Unicast Mac Remote. + ****************************************************************************/ + +struct SandeshUnicastMacRemoteInfo { + 1: string op; + 2: string mac; + 3: string logical_switch; + 4: string dest_ip; +} + +traceobject sandesh OvsdbUnicastMacRemote { + 1: SandeshUnicastMacRemoteInfo ucast_remote; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index a91de4c60d7..ba54413d7b4 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -89,7 +89,7 @@ ovsdb_wrapper_idl_encode_monitor_request(struct ovsdb_idl *idl) return ovsdb_idl_encode_monitor_request(idl); } -void +void ovsdb_wrapper_idl_msg_process(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) { ovsdb_idl_msg_process(idl, msg); @@ -285,7 +285,7 @@ char * ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row) { struct vteprec_physical_locator *p = - row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; return p->dst_ip; } @@ -294,7 +294,7 @@ ovsdb_wrapper_add_physical_locator(struct ovsdb_idl_txn *txn, struct ovsdb_idl_row *row, const char *dip) { struct vteprec_physical_locator *p = - row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; if (p == NULL) p = vteprec_physical_locator_insert(txn); vteprec_physical_locator_set_dst_ip(p, dip); @@ -305,7 +305,7 @@ void ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *row) { struct vteprec_physical_locator *p = - row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; + row ? CONTAINER_OF(row, struct vteprec_physical_locator, header_) : NULL; vteprec_physical_locator_delete(p); } @@ -313,7 +313,7 @@ ovsdb_wrapper_delete_physical_locator(struct ovsdb_idl_row *row) char * ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row) { - struct vteprec_ucast_macs_local *mac = + struct vteprec_ucast_macs_local *mac = row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; return mac->MAC; } @@ -321,7 +321,7 @@ ovsdb_wrapper_ucast_mac_local_mac(struct ovsdb_idl_row *row) char * ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row) { - struct vteprec_ucast_macs_local *mac = + struct vteprec_ucast_macs_local *mac = row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; return mac->ipaddr; } @@ -329,7 +329,7 @@ ovsdb_wrapper_ucast_mac_local_ip(struct ovsdb_idl_row *row) char * ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row) { - struct vteprec_ucast_macs_local *mac = + struct vteprec_ucast_macs_local *mac = row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; if (mac->logical_switch) { return mac->logical_switch->name; @@ -340,7 +340,7 @@ ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row) char * ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row) { - struct vteprec_ucast_macs_local *mac = + struct vteprec_ucast_macs_local *mac = row ? CONTAINER_OF(row, struct vteprec_ucast_macs_local, header_) : NULL; if (mac->locator) { return mac->locator->dst_ip; @@ -348,6 +348,69 @@ ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row) return NULL; } +/* unicast mac remote */ +void +obvsdb_wrapper_add_ucast_mac_remote(struct ovsdb_idl_txn *txn, const char *mac, + struct ovsdb_idl_row *ls, const char *dest_ip) +{ + struct vteprec_ucast_macs_remote *ucast = + vteprec_ucast_macs_remote_insert(txn); + vteprec_ucast_macs_remote_set_MAC(ucast, mac); + struct vteprec_logical_switch *l_switch = + ls? CONTAINER_OF(ls, struct vteprec_logical_switch, header_) : NULL; + vteprec_ucast_macs_remote_set_logical_switch(ucast, l_switch); + struct vteprec_physical_locator *p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dest_ip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + vteprec_ucast_macs_remote_set_locator(ucast, p); +} + +void +ovsdb_wrapper_delete_ucast_mac_remote(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_remote *ucast = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_remote, header_) : NULL; + vteprec_ucast_macs_remote_delete(ucast); +} + +char * +ovsdb_wrapper_ucast_mac_remote_mac(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_remote *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_remote, header_) : NULL; + return mac->MAC; +} + +char * +ovsdb_wrapper_ucast_mac_remote_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_remote *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_remote, header_) : NULL; + return mac->ipaddr; +} + +char * +ovsdb_wrapper_ucast_mac_remote_logical_switch(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_remote *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_remote, header_) : NULL; + if (mac->logical_switch) { + return mac->logical_switch->name; + } + return NULL; +} + +char * +ovsdb_wrapper_ucast_mac_remote_dst_ip(struct ovsdb_idl_row *row) +{ + struct vteprec_ucast_macs_remote *mac = + row ? CONTAINER_OF(row, struct vteprec_ucast_macs_remote, header_) : NULL; + if (mac->locator) { + return mac->locator->dst_ip; + } + return NULL; +} + /* multicast mac local */ void ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index bfc642a728e..e799ba4c927 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -73,6 +73,13 @@ char *ovsdb_wrapper_ucast_mac_local_logical_switch(struct ovsdb_idl_row *row); char *ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row); /* unicast mac remote */ +void obvsdb_wrapper_add_ucast_mac_remote(struct ovsdb_idl_txn *txn, + const char *mac, struct ovsdb_idl_row *ls, const char *dest_ip); +void ovsdb_wrapper_delete_ucast_mac_remote(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_remote_mac(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_remote_ip(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_remote_logical_switch(struct ovsdb_idl_row *row); +char *ovsdb_wrapper_ucast_mac_remote_dst_ip(struct ovsdb_idl_row *row); /* multicast mac local */ void ovsdb_wrapper_delete_mcast_mac_local(struct ovsdb_idl_row *row); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index 27db947ed66..9b2f540db24 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -3,53 +3,64 @@ */ extern "C" { -#include +#include }; - #include -#include +#include #include +#include +#include #include -#include -#include +#include +#include +#include using namespace AGENT; +using OVSDB::UnicastMacRemoteEntry; +using OVSDB::UnicastMacRemoteTable; +using OVSDB::OvsdbDBEntry; +using OVSDB::OvsdbDBObject; -UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), - is_vxlan_nh_(true), nh_(NULL) { -} - -UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - const UnicastMacRemoteEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), - is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { +UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, + const std::string mac, const std::string logical_switch) : + OvsdbDBEntry(table), mac_(mac), logical_switch_name_(logical_switch) { } -UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - const NextHop *entry) : OvsdbDBEntry(table), dip_(""), - is_vxlan_nh_(false), nh_(entry) { - if (entry->GetType() == NextHop::TUNNEL) { - const TunnelNH *tunnel_nh = static_cast(entry); - if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { - dip_ = tunnel_nh->GetDip()->to_string(); - is_vxlan_nh_ = true; - } - } +UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, + const Layer2RouteEntry *entry) : OvsdbDBEntry(table), + mac_(entry->GetAddress().ToString()), + logical_switch_name_(UuidToString(entry->vrf()->vn()->GetUuid())) { } -UnicastMacRemoteEntry::UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), - is_vxlan_nh_(true), nh_(NULL) { +UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, + const UnicastMacRemoteEntry *entry) : OvsdbDBEntry(table), + mac_(entry->mac_), logical_switch_name_(entry->logical_switch_name_), + dest_ip_(entry->dest_ip_) { } -UnicastMacRemoteEntry::~UnicastMacRemoteEntry() { -} +UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, + struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), + mac_(ovsdb_wrapper_ucast_mac_remote_mac(entry)), + logical_switch_name_(ovsdb_wrapper_ucast_mac_remote_logical_switch(entry)), + dest_ip_() { + const char *dest_ip = ovsdb_wrapper_ucast_mac_remote_dst_ip(entry); + if (dest_ip) { + dest_ip_ = std::string(dest_ip); + } +}; void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { - if (!is_vxlan_nh_) - return; - ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *logical_switch = + static_cast(l_table->GetReference(&key)); + logical_switch_ = logical_switch; + if (ovs_entry_ == NULL && !dest_ip_.empty()) { + obvsdb_wrapper_add_ucast_mac_remote(txn, mac_.c_str(), + logical_switch->ovs_entry(), dest_ip_.c_str()); + SendTrace(UnicastMacRemoteEntry::ADD_REQ); + } } void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { @@ -57,71 +68,106 @@ void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { } void UnicastMacRemoteEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { - if (!is_vxlan_nh_) - return; - ovsdb_wrapper_delete_physical_locator(ovs_entry_); + ovsdb_wrapper_delete_ucast_mac_remote(ovs_entry_); + SendTrace(UnicastMacRemoteEntry::DEL_REQ); +} + +void UnicastMacRemoteEntry::OvsdbChange() { + if (!IsResolved()) + table_->NotifyEvent(this, KSyncEntry::ADD_CHANGE_REQ); } bool UnicastMacRemoteEntry::Sync(DBEntry *db_entry) { - NextHop *entry = static_cast(db_entry); - if (entry->GetType() == NextHop::TUNNEL) { - TunnelNH *tunnel_nh = static_cast(entry); - if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { - if (dip_ != tunnel_nh->GetDip()->to_string()) { - // We don't handle dest ip change; - assert(0); - } + const Layer2RouteEntry *entry = + static_cast(db_entry); + std::string dest_ip; + const NextHop *nh = entry->GetActiveNextHop(); + if (nh && nh->GetType() == NextHop::TUNNEL) { + const TunnelNH *tunnel = static_cast(nh); + if (tunnel->GetTunnelType().GetType() == TunnelType::VXLAN) { + dest_ip = tunnel->GetDip()->to_string(); } } + if (dest_ip_ != dest_ip) { + dest_ip_ = dest_ip; + return true; + } return false; } bool UnicastMacRemoteEntry::IsLess(const KSyncEntry &entry) const { - const UnicastMacRemoteEntry &pl_entry = + const UnicastMacRemoteEntry &ucast = static_cast(entry); - if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { - return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); - } else if (!is_vxlan_nh_) { - return nh_ < pl_entry.nh_; - } - return (dip_ < pl_entry.dip_); + if (mac_ != ucast.mac_) + return mac_ < ucast.mac_; + return logical_switch_name_ < ucast.logical_switch_name_; } KSyncEntry *UnicastMacRemoteEntry::UnresolvedReference() { -#if 0 - PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); - PhysicalSwitchEntry key(p_table, device_name_.c_str()); - PhysicalSwitchEntry *p_switch = - static_cast(p_table->GetReference(&key)); - if (!p_switch->IsResolved()) { - return p_switch; + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *l_switch = + static_cast(l_table->GetReference(&key)); + if (!l_switch->IsResolved()) { + return l_switch; } -#endif return NULL; } -UnicastMacRemoteTable::UnicastMacRemoteTable(OvsdbClientIdl *idl, - DBTable *table) : OvsdbDBObject(idl, table) { - idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, +void UnicastMacRemoteEntry::SendTrace(Trace event) const { + SandeshUnicastMacRemoteInfo info; + switch (event) { + case ADD_REQ: + info.set_op("Add Requested"); + break; + case DEL_REQ: + info.set_op("Delete Requested"); + break; + case ADD_ACK: + info.set_op("Add Received"); + break; + case DEL_ACK: + info.set_op("Delete Received"); + break; + default: + info.set_op("unknown"); + } + info.set_mac(mac_); + info.set_logical_switch(logical_switch_name_); + info.set_dest_ip(dest_ip_); + OVSDB_TRACE(UnicastMacRemote, info); +} + +UnicastMacRemoteTable::UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { + idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE, boost::bind(&UnicastMacRemoteTable::OvsdbNotify, this, _1, _2)); } UnicastMacRemoteTable::~UnicastMacRemoteTable() { - client_idl_->UnRegister(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE); } void UnicastMacRemoteTable::OvsdbNotify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_ucast_mac_remote_mac(row); + const char *logical_switch = + ovsdb_wrapper_ucast_mac_remote_logical_switch(row); + /* if logical switch is not available ignore nodtification */ + if (logical_switch == NULL) + return; + const char *dest_ip = ovsdb_wrapper_ucast_mac_remote_dst_ip(row); + UnicastMacRemoteEntry key(this, mac, logical_switch); if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Physical Locator %s\n", - ovsdb_wrapper_physical_locator_dst_ip(row)); - UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); - NotifyDelete((OvsdbDBEntry*)&key); + NotifyDeleteOvsdb((OvsdbDBEntry*)&key); + if (dest_ip) + key.dest_ip_ = std::string(dest_ip); + key.SendTrace(UnicastMacRemoteEntry::DEL_ACK); } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of Physical Locator %s\n", - ovsdb_wrapper_physical_locator_dst_ip(row)); - UnicastMacRemoteEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); - NotifyAdd((OvsdbDBEntry*)&key, row); + NotifyAddOvsdb((OvsdbDBEntry*)&key, row); + if (dest_ip) + key.dest_ip_ = std::string(dest_ip); + key.SendTrace(UnicastMacRemoteEntry::ADD_ACK); } else { assert(0); } @@ -135,14 +181,14 @@ KSyncEntry *UnicastMacRemoteTable::Alloc(const KSyncEntry *key, uint32_t index) } KSyncEntry *UnicastMacRemoteTable::DBToKSyncEntry(const DBEntry* db_entry) { - const NextHop *entry = - static_cast(db_entry); + const Layer2RouteEntry *entry = + static_cast(db_entry); UnicastMacRemoteEntry *key = new UnicastMacRemoteEntry(this, entry); return static_cast(key); } OvsdbDBEntry *UnicastMacRemoteTable::AllocOvsEntry(struct ovsdb_idl_row *row) { - UnicastMacRemoteEntry *entry = new UnicastMacRemoteEntry(this, row); - return static_cast(entry); + UnicastMacRemoteEntry key(this, row); + return static_cast(Create(&key)); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h index 94cee9c1662..9736410ac85 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -2,55 +2,66 @@ * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ -#ifndef __UNICAST_MAC_REMOTE_OVSDB_H__ -#define __UNICAST_MAC_REMOTE_OVSDB_H__ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_UNICAST_MAC_REMOTE_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_UNICAST_MAC_REMOTE_OVSDB_H_ +#include +#include #include -class KSyncEntry; -class OvsdbDBEntry; -class UnicastMacRemoteEntry; +class Layer2RouteEntry; +namespace OVSDB { class UnicastMacRemoteTable : public OvsdbDBObject { public: UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table); virtual ~UnicastMacRemoteTable(); void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); KSyncEntry *DBToKSyncEntry(const DBEntry*); OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); private: - friend class UnicastMacRemoteEntry; DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteTable); }; class UnicastMacRemoteEntry : public OvsdbDBEntry { public: - UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - std::string l_switch_name, MacAddress mac_, std::string dest_ip); - UnicastMacRemoteEntry(UnicastMacRemoteTable *table, - const UnicastMacRemoteEntry *key); - UnicastMacRemoteEntry(UnicastMacRemoteTable *table, const NextHop *entry); - UnicastMacRemoteEntry(UnicastMacRemoteTable *table, + enum Trace { + ADD_REQ, + DEL_REQ, + ADD_ACK, + DEL_ACK, + }; + UnicastMacRemoteEntry(OvsdbDBObject *table, const std::string mac, + const std::string logical_switch); + UnicastMacRemoteEntry(OvsdbDBObject *table, const Layer2RouteEntry *entry); + UnicastMacRemoteEntry(OvsdbDBObject *table, const UnicastMacRemoteEntry *key); + UnicastMacRemoteEntry(OvsdbDBObject *table, struct ovsdb_idl_row *entry); - ~UnicastMacRemoteEntry(); void AddMsg(struct ovsdb_idl_txn *); void ChangeMsg(struct ovsdb_idl_txn *); void DeleteMsg(struct ovsdb_idl_txn *); + + void OvsdbChange(); + bool Sync(DBEntry*); bool IsLess(const KSyncEntry&) const; - std::string ToString() const {return "Unicast Remote Entry";} + std::string ToString() const {return "Unicast Mac Remote";} KSyncEntry* UnresolvedReference(); private: + void SendTrace(Trace event) const; + friend class UnicastMacRemoteTable; - std::string l_switch_name_; - MacAddress mac_; + std::string mac_; + std::string logical_switch_name_; std::string dest_ip_; - + KSyncEntryPtr logical_switch_; DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteEntry); }; +}; -#endif //__UNICAST_MAC_REMOTE_OVSDB_H__ +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_UNICAST_MAC_REMOTE_OVSDB_H_ From 2681204b39ed4532eee0232f4750c1e136d90632 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 20 Oct 2014 11:44:18 -0700 Subject: [PATCH 011/218] Adding support for exporting routes to ovsdb. Skipping routes imported from same ovsdb. --- .../ovsdb_client/ovsdb_client_idl.cc | 2 + .../ovsdb_client/ovsdb_client_idl.h | 2 + .../ovs_tor_agent/ovsdb_client/ovsdb_entry.cc | 7 +- .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 99 +++++++++++++++++-- .../ovsdb_client/unicast_mac_remote_ovsdb.h | 31 +++++- 5 files changed, 130 insertions(+), 11 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 0b4f22e818b..fccd15b5f0b 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -20,6 +20,7 @@ extern "C" { #include #include #include +#include #if 0 #include #endif @@ -82,6 +83,7 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, (DBTable *)agent->device_manager()->logical_port_table())); unicast_mac_local_ovsdb_.reset(new UnicastMacLocalOvsdb(this, route_peer())); + vrf_ovsdb_.reset(new VrfOvsdbObject(this, (DBTable *)agent->vrf_table())); #if 0 //TODO physical_locator_table_.reset(new PhysicalLocatorTable(this, (DBTable *)agent->nexthop_table())); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 1c8cef6a482..9cb838033fc 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -28,6 +28,7 @@ class PhysicalPortTable; class VlanPortBindingTable; class PhysicalLocatorTable; class UnicastMacLocalOvsdb; +class VrfOvsdbObject; class OvsdbEntryBase; class OvsdbClientIdl { @@ -94,6 +95,7 @@ class OvsdbClientIdl { std::auto_ptr physical_port_table_; std::auto_ptr vlan_port_table_; std::auto_ptr unicast_mac_local_ovsdb_; + std::auto_ptr vrf_ovsdb_; #if 0 //TODO std::auto_ptr physical_locator_table_; #endif diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc index 45061c37e47..f6ea687d5f1 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc @@ -6,6 +6,7 @@ extern "C" { } #include #include +#include using OVSDB::OvsdbEntry; using OVSDB::OvsdbDBEntry; @@ -134,14 +135,14 @@ void OvsdbDBEntry::Ack(bool success) { // On Failure try again if (IsDelAckWaiting()) { //Delete(); - printf("Delete Transaction failed for %s\n", ToString().c_str()); + OVSDB_TRACE(Error, "Delete Transaction failed for " + ToString()); object->NotifyEvent(this, KSyncEntry::DEL_ACK); } else if (IsAddChangeAckWaiting()) { - printf("Add Transaction failed for %s\n", ToString().c_str()); + OVSDB_TRACE(Error, "Add Transaction failed for " + ToString()); object->NotifyEvent(this, KSyncEntry::ADD_ACK); //Add(); } else { - printf("Ovsdb Delete Transaction failed for %s\n", ToString().c_str()); + OVSDB_TRACE(Error, "Ovsdb Delete Transaction failed for " + ToString()); object->OvsdbNotify(OvsdbClientIdl::OVSDB_ADD, ovs_entry_); delete this; //Delete(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index 9b2f540db24..c5fa624c2cf 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -19,12 +19,14 @@ extern "C" { using namespace AGENT; using OVSDB::UnicastMacRemoteEntry; using OVSDB::UnicastMacRemoteTable; +using OVSDB::VrfOvsdbObject; using OVSDB::OvsdbDBEntry; using OVSDB::OvsdbDBObject; UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, const std::string mac, const std::string logical_switch) : - OvsdbDBEntry(table), mac_(mac), logical_switch_name_(logical_switch) { + OvsdbDBEntry(table), mac_(mac), logical_switch_name_(logical_switch), + self_exported_route_(false) { } UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, @@ -51,6 +53,9 @@ UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, }; void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { + if (self_exported_route_) { + return; + } LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); LogicalSwitchEntry key(l_table, logical_switch_name_.c_str()); LogicalSwitchEntry *logical_switch = @@ -68,6 +73,7 @@ void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { } void UnicastMacRemoteEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + logical_switch_ = NULL; ovsdb_wrapper_delete_ucast_mac_remote(ovs_entry_); SendTrace(UnicastMacRemoteEntry::DEL_REQ); } @@ -88,11 +94,18 @@ bool UnicastMacRemoteEntry::Sync(DBEntry *db_entry) { dest_ip = tunnel->GetDip()->to_string(); } } + bool change = false; if (dest_ip_ != dest_ip) { dest_ip_ = dest_ip; - return true; + change = true; + } + bool self_exported_route = + (entry->FindPath((Peer *)table_->client_idl()->route_peer()) != NULL); + if (self_exported_route_ != self_exported_route) { + self_exported_route_ = self_exported_route; + change = true; } - return false; + return change; } bool UnicastMacRemoteEntry::IsLess(const KSyncEntry &entry) const { @@ -140,12 +153,12 @@ void UnicastMacRemoteEntry::SendTrace(Trace event) const { UnicastMacRemoteTable::UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table) : OvsdbDBObject(idl, table) { - idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE, - boost::bind(&UnicastMacRemoteTable::OvsdbNotify, this, _1, _2)); + //idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE, + // boost::bind(&UnicastMacRemoteTable::OvsdbNotify, this, _1, _2)); } UnicastMacRemoteTable::~UnicastMacRemoteTable() { - client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE); + //client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE); } void UnicastMacRemoteTable::OvsdbNotify(OvsdbClientIdl::Op op, @@ -192,3 +205,77 @@ OvsdbDBEntry *UnicastMacRemoteTable::AllocOvsEntry(struct ovsdb_idl_row *row) { return static_cast(Create(&key)); } +VrfOvsdbObject::VrfOvsdbObject(OvsdbClientIdl *idl, DBTable *table) : + client_idl_(idl), table_(table) { + vrf_listener_id_ = table->Register(boost::bind(&VrfOvsdbObject::VrfNotify, + this, _1, _2)); + client_idl_->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE, + boost::bind(&VrfOvsdbObject::OvsdbRouteNotify, this, _1, _2)); +} + +VrfOvsdbObject::~VrfOvsdbObject() { + table_->Unregister(vrf_listener_id_); + client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_REMOTE); +} + +void VrfOvsdbObject::OvsdbRouteNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { + const char *mac = ovsdb_wrapper_ucast_mac_remote_mac(row); + const char *logical_switch = + ovsdb_wrapper_ucast_mac_remote_logical_switch(row); + /* if logical switch is not available ignore notification */ + if (logical_switch == NULL) + return; + LogicalSwitchMap::iterator it = logical_switch_map_.find(logical_switch); + if (it == logical_switch_map_.end()) { + // TODO encode the row delete and send + return; + } + const char *dest_ip = ovsdb_wrapper_ucast_mac_remote_dst_ip(row); + UnicastMacRemoteTable *table= it->second->l2_table.get(); + UnicastMacRemoteEntry key(table, mac, logical_switch); + if (op == OvsdbClientIdl::OVSDB_DEL) { + table->NotifyDeleteOvsdb((OvsdbDBEntry*)&key); + if (dest_ip) + key.dest_ip_ = std::string(dest_ip); + key.SendTrace(UnicastMacRemoteEntry::DEL_ACK); + } else if (op == OvsdbClientIdl::OVSDB_ADD) { + table->NotifyAddOvsdb((OvsdbDBEntry*)&key, row); + if (dest_ip) + key.dest_ip_ = std::string(dest_ip); + key.SendTrace(UnicastMacRemoteEntry::ADD_ACK); + } else { + assert(0); + } +} + +void VrfOvsdbObject::VrfNotify(DBTablePartBase *partition, DBEntryBase *e) { + VrfEntry *vrf = static_cast(e); + VrfState *state = static_cast + (vrf->GetState(partition->parent(), vrf_listener_id_)); + if (vrf->IsDeleted()) { + if (state) { + logical_switch_map_.erase(state->logical_switch_name_); + vrf->ClearState(partition->parent(), vrf_listener_id_); + delete state; + } + return; + } + + if (vrf->vn() == NULL) { + return; + } + + if (state == NULL) { + state = new VrfState(); + state->logical_switch_name_ = UuidToString(vrf->vn()->GetUuid()); + // Assumption one vn maps only to one vrf + logical_switch_map_[state->logical_switch_name_] = state; + vrf->SetState(partition->parent(), vrf_listener_id_, state); + + /* We are interested only in L2 Routes */ + state->l2_table.reset(new UnicastMacRemoteTable(client_idl_, + vrf->GetLayer2RouteTable())); + } +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h index 9736410ac85..3f58b47caef 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -12,6 +12,8 @@ class Layer2RouteEntry; namespace OVSDB { +class VrfOvsdbObject; + class UnicastMacRemoteTable : public OvsdbDBObject { public: UnicastMacRemoteTable(OvsdbClientIdl *idl, DBTable *table); @@ -51,16 +53,41 @@ class UnicastMacRemoteEntry : public OvsdbDBEntry { bool IsLess(const KSyncEntry&) const; std::string ToString() const {return "Unicast Mac Remote";} KSyncEntry* UnresolvedReference(); -private: - void SendTrace(Trace event) const; +private: friend class UnicastMacRemoteTable; + friend class VrfOvsdbObject; + void SendTrace(Trace event) const; std::string mac_; std::string logical_switch_name_; std::string dest_ip_; + bool self_exported_route_; KSyncEntryPtr logical_switch_; DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteEntry); }; + +class VrfOvsdbObject { +public: + struct VrfState : DBState { + std::string logical_switch_name_; + std::auto_ptr l2_table; + }; + typedef std::map LogicalSwitchMap; + + VrfOvsdbObject(OvsdbClientIdl *idl, DBTable *table); + virtual ~VrfOvsdbObject(); + + void OvsdbRouteNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); + + void VrfNotify(DBTablePartBase *partition, DBEntryBase *e); +private: + OvsdbClientIdl *client_idl_; + DBTable *table_; + LogicalSwitchMap logical_switch_map_; + DBTableBase::ListenerId vrf_listener_id_; + DISALLOW_COPY_AND_ASSIGN(VrfOvsdbObject); +}; + }; #endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_UNICAST_MAC_REMOTE_OVSDB_H_ From a88a6d74c94cf6ddf2cdc86a1ac18cda1fcc1d4a Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 20 Oct 2014 23:58:14 -0700 Subject: [PATCH 012/218] Removing tunnel type check for exporting routes to OVSDB --- .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index c5fa624c2cf..292ccdc5a72 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -88,11 +88,18 @@ bool UnicastMacRemoteEntry::Sync(DBEntry *db_entry) { static_cast(db_entry); std::string dest_ip; const NextHop *nh = entry->GetActiveNextHop(); + /* + * TOR Agent will not have any local VM so only tunnel nexthops + * are to be looked into + */ if (nh && nh->GetType() == NextHop::TUNNEL) { + /* + * we don't care the about the tunnel type in nh and always program + * the entry to ovsdb expecting vrouter to always handle + * VxLAN encapsulation. + */ const TunnelNH *tunnel = static_cast(nh); - if (tunnel->GetTunnelType().GetType() == TunnelType::VXLAN) { - dest_ip = tunnel->GetDip()->to_string(); - } + dest_ip = tunnel->GetDip()->to_string(); } bool change = false; if (dest_ip_ != dest_ip) { From 6202bab9f59b0834630126902172792283957bba Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Tue, 21 Oct 2014 12:49:52 +0530 Subject: [PATCH 013/218] OVSDB Enhancements 1. Modify the logic used to identify routes that must be exported to controller In existing design, controller-peer looks at the peer-type to decide if path added by it can be exported to controller. Any new type of peer will need modifying this code as well. The design is modified such that, a virtual function in peer specifies if the routes added by peer should be exported to controller. 2. Modify the logic to set the nexthop-ip in route exported to controller. In existing design, agent always sets IP address of VHOST to be the nexthop-ip in the route exported to controller. In case of OVS, agent is exporting route on-behalf of the ToR. In this case the nexthop should actually be that of ToR. The design is modified to get the nexthop-ip from peer Only EVPN routes are using the new API. L3 and Mcast routes will be modified later to use the new API. 3. Add skeletal code for UT of OVS-Peer --- src/vnsw/agent/cmn/agent.cc | 18 ++- src/vnsw/agent/cmn/agent.h | 1 + .../agent/controller/controller_export.cc | 25 ++-- src/vnsw/agent/controller/controller_peer.cc | 15 +- src/vnsw/agent/controller/controller_peer.h | 3 + .../openstack/instance_service_server.cc | 2 +- src/vnsw/agent/oper/agent_path.cc | 8 ++ src/vnsw/agent/oper/agent_path.h | 2 + src/vnsw/agent/oper/agent_route.cc | 4 + src/vnsw/agent/oper/peer.cc | 10 +- src/vnsw/agent/oper/peer.h | 13 +- .../ovs_tor_agent/ovsdb_client/SConscript | 2 + .../ovsdb_client/ovsdb_route_data.cc | 4 + .../ovsdb_client/ovsdb_route_data.h | 1 + .../ovsdb_client/ovsdb_route_peer.cc | 35 ++++- .../ovsdb_client/ovsdb_route_peer.h | 4 + .../ovsdb_client/test/SConscript | 37 +++++ .../ovsdb_client/test/test_ovs_agent_init.cc | 109 +++++++++++++++ .../ovsdb_client/test/test_ovs_agent_init.h | 40 ++++++ .../ovsdb_client/test/test_ovs_route.cc | 130 ++++++++++++++++++ src/vnsw/agent/test-xml/test_xml.cc | 4 + src/vnsw/agent/test-xml/test_xml.h | 6 +- src/vnsw/agent/test-xml/test_xml_validate.cc | 2 +- src/vnsw/agent/test/test_route.cc | 4 +- src/vnsw/agent/test/test_scale_walk.cc | 4 +- src/vnsw/agent/test/test_util.cc | 2 +- 26 files changed, 445 insertions(+), 40 deletions(-) create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/SConscript create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_route.cc diff --git a/src/vnsw/agent/cmn/agent.cc b/src/vnsw/agent/cmn/agent.cc index 41733aaa226..b655198c966 100644 --- a/src/vnsw/agent/cmn/agent.cc +++ b/src/vnsw/agent/cmn/agent.cc @@ -329,15 +329,19 @@ void Agent::InitXenLinkLocalIntf() { void Agent::InitPeers() { // Create peer entries - local_peer_.reset(new Peer(Peer::LOCAL_PEER, LOCAL_PEER_NAME)); - local_vm_peer_.reset(new Peer(Peer::LOCAL_VM_PEER, LOCAL_VM_PEER_NAME)); - linklocal_peer_.reset(new Peer(Peer::LINKLOCAL_PEER, LINKLOCAL_PEER_NAME)); - ecmp_peer_.reset(new Peer(Peer::ECMP_PEER, ECMP_PEER_NAME)); - vgw_peer_.reset(new Peer(Peer::VGW_PEER, VGW_PEER_NAME)); - multicast_peer_.reset(new Peer(Peer::MULTICAST_PEER, MULTICAST_PEER_NAME)); + local_peer_.reset(new Peer(Peer::LOCAL_PEER, LOCAL_PEER_NAME, false)); + local_vm_peer_.reset(new Peer(Peer::LOCAL_VM_PEER, LOCAL_VM_PEER_NAME, + false)); + linklocal_peer_.reset(new Peer(Peer::LINKLOCAL_PEER, LINKLOCAL_PEER_NAME, + false)); + ecmp_peer_.reset(new Peer(Peer::ECMP_PEER, ECMP_PEER_NAME, true)); + vgw_peer_.reset(new Peer(Peer::VGW_PEER, VGW_PEER_NAME, true)); + multicast_peer_.reset(new Peer(Peer::MULTICAST_PEER, MULTICAST_PEER_NAME, + false)); multicast_tree_builder_peer_.reset( new Peer(Peer::MULTICAST_FABRIC_TREE_BUILDER, - MULTICAST_FABRIC_TREE_BUILDER_NAME)); + MULTICAST_FABRIC_TREE_BUILDER_NAME, + false)); } Agent::Agent() : diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h index 3190d00327b..35e576d541c 100644 --- a/src/vnsw/agent/cmn/agent.h +++ b/src/vnsw/agent/cmn/agent.h @@ -363,6 +363,7 @@ class Agent { } Ip4Address router_id() const {return router_id_;} + const Ip4Address *router_ip_ptr() const {return &router_id_;} void set_router_id(const Ip4Address &addr) { router_id_ = addr; set_router_id_configured(true); diff --git a/src/vnsw/agent/controller/controller_export.cc b/src/vnsw/agent/controller/controller_export.cc index 034cb930a11..0c901bcc776 100644 --- a/src/vnsw/agent/controller/controller_export.cc +++ b/src/vnsw/agent/controller/controller_export.cc @@ -118,6 +118,8 @@ void RouteExport::UnicastNotify(AgentXmppChannel *bgp_xmpp_peer, DBTablePartBase *partition, DBEntryBase *e, Agent::RouteTableType type) { AgentRoute *route = static_cast(e); + AgentRouteTable *table = static_cast + (partition->parent()); State *state = static_cast(route->GetState(partition->parent(), id_)); AgentPath *path = route->FindLocalVmPortPath(); @@ -171,7 +173,8 @@ void RouteExport::UnicastNotify(AgentXmppChannel *bgp_xmpp_peer, state->Update(path); state->exported_ = AgentXmppChannel::ControllerSendRouteAdd(bgp_xmpp_peer, - static_cast(route), state->vn_, + static_cast(route), + path->NexthopIp(table->agent()), state->vn_, state->label_, path->GetTunnelBmap(), &path->sg_list(), type, state->path_preference_); } @@ -216,6 +219,8 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, DBTablePartBase *partition, DBEntryBase *e) { AgentRoute *route = static_cast(e); + AgentRouteTable *table = static_cast + (partition->parent()); State *state = static_cast(route->GetState(partition->parent(), id_)); bool route_can_be_dissociated = RouteCanDissociate(route); const Agent *agent = bgp_xmpp_peer->agent(); @@ -301,11 +306,9 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, withdraw = true; } if (withdraw) { - AgentXmppChannel::ControllerSendEvpnRouteDelete(bgp_xmpp_peer, - route, - state->vn_, - withdraw_label, - state->tunnel_type_); + AgentXmppChannel::ControllerSendEvpnRouteDelete + (bgp_xmpp_peer, route, state->vn_, withdraw_label, + state->tunnel_type_); state->evpn_exported_ = false; } } @@ -328,11 +331,11 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, state->vn_ = route->dest_vn_name(); if (associate) { state->evpn_exported_ = - AgentXmppChannel::ControllerSendEvpnRouteAdd(bgp_xmpp_peer, - route, - route->dest_vn_name(), - state->label_, - TunnelType::AllType()); + AgentXmppChannel::ControllerSendEvpnRouteAdd + (bgp_xmpp_peer, route, + active_path->NexthopIp(table->agent()), + route->dest_vn_name(), state->label_, + TunnelType::AllType()); } else { state->evpn_exported_ = AgentXmppChannel::ControllerSendEvpnRouteDelete(bgp_xmpp_peer, diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index da4961da149..ae3020f2cc8 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -1569,6 +1569,7 @@ bool AgentXmppChannel::ControllerSendV4V6UnicastRouteCommon(AgentRoute *route, } bool AgentXmppChannel::ControllerSendEvpnRouteCommon(AgentRoute *route, + const Ip4Address *nh_ip, std::string vn, uint32_t label, uint32_t tunnel_bmap, @@ -1601,11 +1602,9 @@ bool AgentXmppChannel::ControllerSendEvpnRouteCommon(AgentRoute *route, item.entry.nlri.address = rstr.str(); assert(item.entry.nlri.address != "0.0.0.0"); - string rtr(agent_->router_id().to_string()); - autogen::EnetNextHopType nh; nh.af = Address::INET; - nh.address = rtr; + nh.address = nh_ip->to_string(); nh.label = label; item.entry.nlri.ethernet_tag = 0; @@ -1800,6 +1799,7 @@ bool AgentXmppChannel::ControllerSendMcastRouteCommon(AgentRoute *route, bool AgentXmppChannel::ControllerSendEvpnRouteAdd(AgentXmppChannel *peer, AgentRoute *route, + const Ip4Address *nh_ip, std::string vn, uint32_t label, uint32_t tunnel_bmap) { @@ -1809,6 +1809,7 @@ bool AgentXmppChannel::ControllerSendEvpnRouteAdd(AgentXmppChannel *peer, route->vrf()->GetName(), route->ToString(), true, label); return (peer->ControllerSendEvpnRouteCommon(route, + nh_ip, vn, label, tunnel_bmap, @@ -1825,7 +1826,9 @@ bool AgentXmppChannel::ControllerSendEvpnRouteDelete(AgentXmppChannel *peer, CONTROLLER_TRACE(RouteExport, peer->GetBgpPeerName(), route->vrf()->GetName(), route->ToString(), false, label); + Ip4Address nh_ip = Ip4Address(0); return (peer->ControllerSendEvpnRouteCommon(route, + &nh_ip, vn, label, tunnel_bmap, @@ -1834,6 +1837,7 @@ bool AgentXmppChannel::ControllerSendEvpnRouteDelete(AgentXmppChannel *peer, bool AgentXmppChannel::ControllerSendRouteAdd(AgentXmppChannel *peer, AgentRoute *route, + const Ip4Address *nexthop_ip, std::string vn, uint32_t label, TunnelType::TypeBmap bmap, @@ -1858,7 +1862,7 @@ bool AgentXmppChannel::ControllerSendRouteAdd(AgentXmppChannel *peer, type); } if (type == Agent::LAYER2) { - ret = peer->ControllerSendEvpnRouteCommon(route, vn, + ret = peer->ControllerSendEvpnRouteCommon(route, nexthop_ip, vn, label, bmap, true); } return ret; @@ -1892,7 +1896,8 @@ bool AgentXmppChannel::ControllerSendRouteDelete(AgentXmppChannel *peer, type); } if (type == Agent::LAYER2) { - ret = peer->ControllerSendEvpnRouteCommon(route, vn, + Ip4Address nh_ip(0); + ret = peer->ControllerSendEvpnRouteCommon(route, &nh_ip, vn, label, bmap, false); } return ret; diff --git a/src/vnsw/agent/controller/controller_peer.h b/src/vnsw/agent/controller/controller_peer.h index b5ab6abae82..b258a9dc111 100644 --- a/src/vnsw/agent/controller/controller_peer.h +++ b/src/vnsw/agent/controller/controller_peer.h @@ -61,6 +61,7 @@ class AgentXmppChannel { //Add to control-node static bool ControllerSendRouteAdd(AgentXmppChannel *peer, AgentRoute *route, + const Ip4Address *nexthop_ip, std::string vn, uint32_t label, uint32_t tunnel_bmap, @@ -69,6 +70,7 @@ class AgentXmppChannel { const PathPreference &path_preference); static bool ControllerSendEvpnRouteAdd(AgentXmppChannel *peer, AgentRoute *route, + const Ip4Address *nexthop_ip, std::string vn, uint32_t mpls_label, uint32_t tunnel_bmap); @@ -127,6 +129,7 @@ class AgentXmppChannel { bool associate, Agent::RouteTableType type); bool ControllerSendEvpnRouteCommon(AgentRoute *route, + const Ip4Address *nexthop_ip, std::string vn, uint32_t mpls_label, uint32_t tunnel_bmap, diff --git a/src/vnsw/agent/openstack/instance_service_server.cc b/src/vnsw/agent/openstack/instance_service_server.cc index fcb564aa681..4d589dcac39 100644 --- a/src/vnsw/agent/openstack/instance_service_server.cc +++ b/src/vnsw/agent/openstack/instance_service_server.cc @@ -36,7 +36,7 @@ InstanceServiceAsyncHandler::InstanceServiceAsyncHandler(Agent *agent) : io_service_(*(agent->event_manager()->io_service())), agent_(agent), version_(0), vgw_version_(0), - novaPeer_(new Peer(Peer::NOVA_PEER, NOVA_PEER_NAME)), + novaPeer_(new Peer(Peer::NOVA_PEER, NOVA_PEER_NAME, false)), interface_stale_cleaner_(new InterfaceConfigStaleCleaner(agent)), vgw_stale_cleaner_(new ConfigStaleCleaner(agent, boost::bind( &InstanceServiceAsyncHandler::OnVirtualGatewayStaleTimeout, this, _1))) { diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index ebcb5f3ac94..02318a86582 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -881,3 +881,11 @@ bool AgentPath::ChangeCompositeNH(Agent *agent, } return false; } + +const Ip4Address *AgentPath::NexthopIp(Agent *agent) const { + if (peer_ == NULL) { + return agent->router_ip_ptr(); + } + + return peer_->NexthopIp(agent, this); +} diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index 9e510fc863b..a8c1fe47fc6 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -170,6 +170,8 @@ class AgentPath : public Path { } bool ReorderCompositeNH(Agent *agent, CompositeNHKey *nh); bool ChangeCompositeNH(Agent *agent, CompositeNHKey *nh); + // Get nexthop-ip address to be used for path + const Ip4Address *NexthopIp(Agent *agent) const; private: const Peer *peer_; // Nexthop for route. Not used for gateway routes diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index f821d3798a6..aad8f2464ea 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -520,6 +520,10 @@ AgentPath *AgentRoute::FindLocalVmPortPath() const { if (path->peer() == NULL) { continue; } + if (path->peer()->export_to_controller()) { + return const_cast(path); + } + if (path->peer()->GetType() == Peer::ECMP_PEER || path->peer()->GetType() == Peer::VGW_PEER || path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER || diff --git a/src/vnsw/agent/oper/peer.cc b/src/vnsw/agent/oper/peer.cc index 77a1531fad6..4eb023ceffa 100644 --- a/src/vnsw/agent/oper/peer.cc +++ b/src/vnsw/agent/oper/peer.cc @@ -14,16 +14,20 @@ #include #include -Peer::Peer(Type type, const std::string &name) : - type_(type), name_(name){ +Peer::Peer(Type type, const std::string &name, bool export_to_controller) : + type_(type), name_(name), export_to_controller_(export_to_controller) { } Peer::~Peer() { } +const Ip4Address *Peer::NexthopIp(Agent *agent, const AgentPath *path) const { + return agent->router_ip_ptr(); +} + BgpPeer::BgpPeer(const Ip4Address &server_ip, const std::string &name, AgentXmppChannel *bgp_xmpp_peer, DBTableBase::ListenerId id) - : Peer(Peer::BGP_PEER, name), server_ip_(server_ip), id_(id), + : Peer(Peer::BGP_PEER, name, false), server_ip_(server_ip), id_(id), bgp_xmpp_peer_(bgp_xmpp_peer), route_walker_(new ControllerRouteWalker(bgp_xmpp_peer_->agent(), this)) { is_disconnect_walk_ = false; diff --git a/src/vnsw/agent/oper/peer.h b/src/vnsw/agent/oper/peer.h index 3b406044f2c..26fdc38906e 100644 --- a/src/vnsw/agent/oper/peer.h +++ b/src/vnsw/agent/oper/peer.h @@ -24,6 +24,7 @@ class AgentXmppChannel; class ControllerRouteWalker; class VrfTable; +class AgentPath; class Peer { public: @@ -43,7 +44,7 @@ class Peer { OVS_PEER }; - Peer(Type type, const std::string &name); + Peer(Type type, const std::string &name, bool controller_export); virtual ~Peer(); bool IsLess(const Peer *rhs) const { @@ -54,6 +55,10 @@ class Peer { return Compare(rhs); } virtual bool Compare(const Peer *rhs) const {return false;} + // Should we export path from this peer to controller? + virtual bool export_to_controller() const {return export_to_controller_;} + virtual const Ip4Address *NexthopIp(Agent *agent, + const AgentPath *path) const; const std::string &GetName() const { return name_; } const Type GetType() const { return type_; } @@ -61,6 +66,7 @@ class Peer { private: Type type_; std::string name_; + bool export_to_controller_; DISALLOW_COPY_AND_ASSIGN(Peer); }; @@ -123,7 +129,7 @@ class BgpPeer : public Peer { class LocalVmPortPeer : public Peer { public: LocalVmPortPeer(const std::string &name, uint64_t handle) : - Peer(Peer::LOCAL_VM_PORT_PEER, name), handle_(handle) { + Peer(Peer::LOCAL_VM_PORT_PEER, name, true), handle_(handle) { } virtual ~LocalVmPortPeer() { } @@ -142,10 +148,11 @@ class LocalVmPortPeer : public Peer { // ECMP peer class EcmpPeer : public Peer { public: - EcmpPeer() : Peer(Peer::ECMP_PEER, "ECMP") { } + EcmpPeer() : Peer(Peer::ECMP_PEER, "ECMP", true) { } virtual ~EcmpPeer() { } bool Compare(const Peer *rhs) const { return false; } + bool ExportToController() const {return true;} private: DISALLOW_COPY_AND_ASSIGN(EcmpPeer); }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index cc5da7562c8..ff8373e8464 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -39,3 +39,5 @@ libovsdbclient = env.Library('ovsdbclient', 'unicast_mac_remote_ovsdb.cc', ]) env.Requires(libovsdbclient, '#/build/include/openvswitch/include') + +env.SConscript('test/SConscript', exports='AgentEnv', duplicate=0) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc index d50fd99c01d..42220a35a3d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.cc @@ -24,6 +24,10 @@ OvsdbRouteData::OvsdbRouteData(const Peer *peer, uint32_t vxlan_id, tor_vrf_(tor_vrf), router_id_(router_id), dest_vn_name_(dest_vn_name) { } +OvsdbRouteData::OvsdbRouteData(const Peer *peer) : + AgentRouteData(false), peer_(peer), vxlan_id_() { +} + OvsdbRouteData::~OvsdbRouteData() { } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h index 9e9fafd6302..bd3e151c70c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_data.h @@ -14,6 +14,7 @@ class OvsdbRouteData : public AgentRouteData { OvsdbRouteData(const Peer *peer, uint32_t vxlan_id, const Ip4Address &tor_ip, const Ip4Address &router_id, const std::string &tor_vrf, const std::string &dest_vn_name); + OvsdbRouteData(const Peer *peer); virtual ~OvsdbRouteData(); virtual std::string ToString() const; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc index 43303d5f91d..7ee0fea1a21 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc @@ -4,9 +4,12 @@ #include #include +#include +#include + OvsPeer::OvsPeer(const IpAddress &peer_ip, uint64_t gen_id, OvsPeerManager *peer_manager) : - Peer(Peer::OVS_PEER, "OVS-" + peer_ip.to_string()), peer_ip_(peer_ip), + Peer(Peer::OVS_PEER, "OVS-" + peer_ip.to_string(), true), peer_ip_(peer_ip), gen_id_(gen_id), peer_manager_(peer_manager) { } @@ -50,6 +53,32 @@ bool OvsPeer::AddOvsRoute(const boost::uuids::uuid &vn_uuid, return true; } +bool OvsPeer::DeleteOvsRoute(const boost::uuids::uuid &vn_uuid, + const MacAddress &mac) { + Agent *agent = peer_manager_->agent(); + VnEntry *vn = agent->vn_table()->Find(vn_uuid); + if (vn == NULL) + return false; + + VrfEntry *vrf = vn->GetVrf(); + if (vrf == NULL) + return false; + + Layer2AgentRouteTable *table = static_cast + (vrf->GetLayer2RouteTable()); + table->DeleteReq(this, vrf->GetName(), mac, vn->vxlan_id()->vxlan_id(), + new OvsdbRouteData(this)); + return true; +} + +const Ip4Address *OvsPeer::NexthopIp(Agent *agent, + const AgentPath *path) const { + const TunnelNH *nh = dynamic_cast(path->nexthop(agent)); + if (nh == NULL) + return agent->router_ip_ptr(); + return nh->GetDip(); +} + OvsPeerManager::OvsPeerManager(Agent *agent) : gen_id_(0), agent_(agent) { } @@ -71,3 +100,7 @@ void OvsPeerManager::Free(OvsPeer *peer) { Agent *OvsPeerManager::agent() const { return agent_; } + +uint32_t OvsPeerManager::Size() const { + return table_.size(); +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h index 00e5113da22..8ec695db8f7 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h @@ -16,8 +16,11 @@ class OvsPeer : public Peer { virtual ~OvsPeer(); bool Compare(const Peer *rhs) const; + const Ip4Address *NexthopIp(Agent *agent, const AgentPath *path) const; bool AddOvsRoute(const boost::uuids::uuid &vn_uuid, const MacAddress &mac, Ip4Address &tor_ip); + bool DeleteOvsRoute(const boost::uuids::uuid &vn_uuid, + const MacAddress &mac); private: IpAddress peer_ip_; uint64_t gen_id_; @@ -39,6 +42,7 @@ class OvsPeerManager { OvsPeer *Allocate(const IpAddress &peer_ip); void Free(OvsPeer *peer); + uint32_t Size() const; Agent *agent() const; private: diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/SConscript new file mode 100644 index 00000000000..738b40fbcf9 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/SConscript @@ -0,0 +1,37 @@ +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# + +# -*- mode: python; -*- + +import sys +if sys.platform == 'darwin': + Return() + +import re +Import('AgentEnv') +env = AgentEnv.Clone() + +# test specific modifications +AgentEnv.MakeTestEnv(env) + +env.Append(LIBPATH = [ '../../../tables' ]) +env.Append(LIBPATH = ['./']) +env.Append(LIBPATH = ['../']) +env.Append(LIBS = [ 'physical_devices']) +env.Append(LIBS = [ 'control_node_mock']) +env.Prepend(LIBS = [ 'test_ovs_agent_init']) +env.Prepend(LIBS = [ 'ovsdbclient', 'openvswitch']) + +env.Library('test_ovs_agent_init', 'test_ovs_agent_init.cc') + +agent_suite = [] +flaky_agent_suite = [] +test_ovs_route = AgentEnv.MakeTestCmd(env, 'test_ovs_route', agent_suite) + +flaky_test = env.TestSuite('agent-flaky-test', flaky_agent_suite) +env.Alias('ovsdb_client:flaky_test', flaky_test) + +test = env.TestSuite('agent-test', agent_suite) +env.Alias('agent:agent_test', test) +Return('agent_suite') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.cc new file mode 100644 index 00000000000..6d3dafb991d --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.cc @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "test/test_init.h" +#include +#include "test_ovs_agent_init.h" + +TestOvsAgentInit::TestOvsAgentInit() : TestAgentInit() { +} + +TestOvsAgentInit::~TestOvsAgentInit() { + device_manager_.reset(); +} + +/**************************************************************************** + * Initialization routines + ***************************************************************************/ +// Create the basic modules for agent operation. +// Optional modules or modules that have different implementation are created +// by init module +void TestOvsAgentInit::CreateModules() { + TestAgentInit::CreateModules(); + device_manager_.reset(new PhysicalDeviceManager(agent())); + agent()->set_device_manager(device_manager_.get()); +} + +void TestOvsAgentInit::CreateDBTables() { + TestAgentInit::CreateDBTables(); + device_manager_->CreateDBTables(agent()->db()); +} + +void TestOvsAgentInit::RegisterDBClients() { + TestAgentInit::RegisterDBClients(); + device_manager_->RegisterDBClients(); +} + +void TestOvsAgentInit::CreatePeers() { + ovs_peer_manager_.reset(new OvsPeerManager(agent())); +} + +/**************************************************************************** + * Access routines + ****************************************************************************/ +PhysicalDeviceManager *TestOvsAgentInit::device_manager() const { + return device_manager_.get(); +} + +OvsPeerManager *TestOvsAgentInit::ovs_peer_manager() const { + return ovs_peer_manager_.get(); +} + +TestClient *OvsTestInit(const char *init_file, bool ksync_init) { + TestClient *client = new TestClient(new TestOvsAgentInit()); + TestOvsAgentInit *init = + static_cast(client->agent_init()); + Agent *agent = client->agent(); + + AgentParam *param = client->param(); + init->set_agent_param(param); + // Read agent parameters from config file and arguments + init->ProcessOptions(init_file, "test"); + param->set_agent_stats_interval(AgentParam::kAgentStatsInterval); + param->set_flow_stats_interval(AgentParam::kFlowStatsInterval); + param->set_vrouter_stats_interval(AgentParam::kVrouterStatsInterval); + + // Initialize the agent-init control class + int introspect_port = 0; + Sandesh::InitGeneratorTest("VNSWAgent", "Agent", "Test", "Test", + agent->event_manager(), introspect_port, NULL); + + init->set_ksync_enable(false); + init->set_packet_enable(true); + init->set_services_enable(true); + init->set_create_vhost(false); + init->set_uve_enable(true); + init->set_vgw_enable(false); + init->set_router_id_dep_enable(false); + param->set_test_mode(true); + agent->set_ksync_sync_mode(true); + + // Initialize agent and kick start initialization + init->Start(); + WaitForInitDone(agent); + + client->Init(); + client->WaitForIdle(); + client->SetFlowFlushExclusionPolicy(); + client->SetFlowAgeExclusionPolicy(); + + AsioRun(); + + return client; +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h new file mode 100644 index 00000000000..114966ee195 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef vnsw_test_ovs_agent_init_hpp +#define vnsw_test_ovs_agent_init_hpp + +#include +#include +#include +#include + +class Agent; +class AgentParam; +class TestClient; +class OvsPeerManager; + +TestClient *OvsTestInit(const char *init_file, bool ksync_init); + +// The class to drive agent initialization. +// Defines control parameters used to enable/disable agent features +class TestOvsAgentInit : public TestAgentInit { +public: + TestOvsAgentInit(); + virtual ~TestOvsAgentInit(); + + void CreatePeers(); + void CreateModules(); + void CreateDBTables(); + void RegisterDBClients(); + + PhysicalDeviceManager *device_manager() const; + OvsPeerManager *ovs_peer_manager() const; +private: + std::auto_ptr device_manager_; + std::auto_ptr ovs_peer_manager_; + DISALLOW_COPY_AND_ASSIGN(TestOvsAgentInit); +}; + +#endif // vnsw_test_ovs_agent_init_hpp diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_route.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_route.cc new file mode 100644 index 00000000000..c4107fc09e0 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/test/test_ovs_route.cc @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "base/os.h" +#include "testing/gunit.h" + +#include +#include +#include +#include +#include + +#include + +#include "cfg/cfg_init.h" +#include "cfg/cfg_interface.h" +#include "pkt/pkt_init.h" +#include "services/services_init.h" +#include "ksync/ksync_init.h" +#include "oper/interface_common.h" +#include "oper/nexthop.h" +#include "oper/tunnel_nh.h" +#include "route/route.h" +#include "oper/vrf.h" +#include "oper/mpls.h" +#include "oper/vm.h" +#include "oper/vn.h" +#include "filter/acl.h" +#include "openstack/instance_service_server.h" +#include "test_cmn_util.h" +#include "vr_types.h" + +#include "openstack/instance_service_server.h" +#include "xmpp/xmpp_init.h" +#include "xmpp/test/xmpp_test_util.h" +#include "vr_types.h" +#include "control_node_mock.h" +#include "xml/xml_pugi.h" +#include "controller/controller_peer.h" +#include "controller/controller_export.h" +#include "controller/controller_vrf_export.h" + +#include "physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h" +#include "test_ovs_agent_init.h" + +using namespace pugi; + +EventManager evm1; +ServerThread *thread1; +test::ControlNodeMock *bgp_peer1; + +EventManager evm2; +ServerThread *thread2; +test::ControlNodeMock *bgp_peer2; + +void RouterIdDepInit(Agent *agent) { + Agent::GetInstance()->controller()->Connect(); +} + +void StartControlNodeMock() { + thread1 = new ServerThread(&evm1); + bgp_peer1 = new test::ControlNodeMock(&evm1, "127.0.0.1"); + + Agent::GetInstance()->set_controller_ifmap_xmpp_server("127.0.0.1", 0); + Agent::GetInstance()->set_controller_ifmap_xmpp_port(bgp_peer1->GetServerPort(), 0); + Agent::GetInstance()->set_dns_server("", 0); + Agent::GetInstance()->set_dns_server_port(bgp_peer1->GetServerPort(), 0); + thread1->Start(); +} + +void StopControlNodeMock() { + Agent::GetInstance()->controller()->DisConnect(); + client->WaitForIdle(); + TcpServerManager::DeleteServer(Agent::GetInstance()->controller_ifmap_xmpp_client(0)); + + bgp_peer1->Shutdown(); + client->WaitForIdle(); + delete bgp_peer1; + + evm1.Shutdown(); + thread1->Join(); + delete thread1; + + client->WaitForIdle(); +} + +class OvsRouteTest : public ::testing::Test { +protected: + OvsRouteTest() { + } + + virtual void SetUp() { + agent_ = Agent::GetInstance(); + init_ = static_cast(client->agent_init()); + peer_manager_ = init_->ovs_peer_manager(); + client->Reset(); + } + + virtual void TearDown() { + //Clean up any pending routes in conrol node mock + bgp_peer1->Clear(); + EXPECT_EQ(peer_manager_->Size(), 0); + } + + Agent *agent_; + TestOvsAgentInit *init_; + OvsPeerManager *peer_manager_; +}; + +TEST_F(OvsRouteTest, OvsPeer_1) { + IpAddress server = Ip4Address::from_string("1.1.1.1"); + OvsPeer *peer = peer_manager_->Allocate(server); + EXPECT_TRUE(peer->export_to_controller()); + peer_manager_->Free(peer); +} + +TEST_F(OvsRouteTest, RouteTest_1) { +} + +int main(int argc, char *argv[]) { + //::testing::InitGoogleTest(&argc, argv); + GETUSERARGS(); + client = OvsTestInit(init_file, ksync_init); + StartControlNodeMock(); + int ret = RUN_ALL_TESTS(); + StopControlNodeMock(); + + return ret; +} diff --git a/src/vnsw/agent/test-xml/test_xml.cc b/src/vnsw/agent/test-xml/test_xml.cc index 06e67a85f0e..39327c36963 100644 --- a/src/vnsw/agent/test-xml/test_xml.cc +++ b/src/vnsw/agent/test-xml/test_xml.cc @@ -137,6 +137,10 @@ void AgentUtXmlTest::AddValidateEntry(const std::string &name, AgentUtXmlTest::AgentUtXmlTestConfigCreateFn AgentUtXmlTest::GetConfigCreateFn(const std::string &name) { AgentUtXmlTestConfigFactory::iterator iter = config_factory_.find(name); + if (iter == config_factory_.end()) { + return AgentUtXmlTest::AgentUtXmlTestConfigCreateFn(); + } + return iter->second; } diff --git a/src/vnsw/agent/test-xml/test_xml.h b/src/vnsw/agent/test-xml/test_xml.h index b9a8d2337a7..efd84a49f70 100644 --- a/src/vnsw/agent/test-xml/test_xml.h +++ b/src/vnsw/agent/test-xml/test_xml.h @@ -86,7 +86,7 @@ class AgentUtXmlTestCase { public: AgentUtXmlTestCase(const std::string &name, const pugi::xml_node &node, AgentUtXmlTest *test); - ~AgentUtXmlTestCase(); + virtual ~AgentUtXmlTestCase(); AgentUtXmlTest *test() { return test_; } virtual bool ReadXml(); @@ -139,7 +139,7 @@ class AgentUtXmlNode { class AgentUtXmlLink : public AgentUtXmlNode { public: AgentUtXmlLink(const pugi::xml_node &node, AgentUtXmlTestCase *test_case); - ~AgentUtXmlLink(); + virtual ~AgentUtXmlLink(); virtual bool ReadXml(); virtual bool ToXml(pugi::xml_node *parent); @@ -184,7 +184,7 @@ class AgentUtXmlPacket : public AgentUtXmlNode { public: AgentUtXmlPacket(const std::string &name, const pugi::xml_node &node, AgentUtXmlTestCase *test_case); - ~AgentUtXmlPacket(); + virtual ~AgentUtXmlPacket(); virtual bool ReadXml(); virtual bool ToXml(pugi::xml_node *parent); diff --git a/src/vnsw/agent/test-xml/test_xml_validate.cc b/src/vnsw/agent/test-xml/test_xml_validate.cc index bec5906620e..9742165663d 100644 --- a/src/vnsw/agent/test-xml/test_xml_validate.cc +++ b/src/vnsw/agent/test-xml/test_xml_validate.cc @@ -96,7 +96,7 @@ bool AgentUtXmlValidate::ReadXml() { for (xml_node n = node().first_child(); n; n = n.next_sibling()) { uuid id; string name; - AgentUtXmlValidationNode *val = false; + AgentUtXmlValidationNode *val = NULL; AgentUtXmlTest::AgentUtXmlTestValidateCreateFn fn = test_case()->test()->GetValidateCreateFn(n.name()); diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index f11decadf28..f8a60f9fa10 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -959,7 +959,7 @@ class TestNhState : public DBState { class TestNhPeer : public Peer { public: - TestNhPeer() : Peer(BGP_PEER, "TestNH"), dummy_(0) { }; + TestNhPeer() : Peer(BGP_PEER, "TestNH", false), dummy_(0) { }; int dummy_; }; @@ -1498,7 +1498,7 @@ TEST_F(RouteTest, PathPreference_1) { CreateVmportEnv(input, 1); client->WaitForIdle(); - Peer peer(Peer::LOCAL_VM_PORT_PEER, "test_peer"); + Peer peer(Peer::LOCAL_VM_PORT_PEER, "test_peer", true); Ip4Address ip = Ip4Address::from_string("1.1.1.10"); //Enqueue path change for non existent path DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); diff --git a/src/vnsw/agent/test/test_scale_walk.cc b/src/vnsw/agent/test/test_scale_walk.cc index 4e8266bae40..9a2c5b9dc4a 100644 --- a/src/vnsw/agent/test/test_scale_walk.cc +++ b/src/vnsw/agent/test/test_scale_walk.cc @@ -41,7 +41,7 @@ TEST_F(AgentBasicScaleTest, Basic) { BuildVmPortEnvironment(); //Create a walker and pass callback - Peer *dummy_peer = new Peer(Peer::BGP_PEER, "dummy_peer"); + Peer *dummy_peer = new Peer(Peer::BGP_PEER, "dummy_peer", false); ControllerRouteWalkerTest *route_walker_test = new ControllerRouteWalkerTest(dummy_peer); SetWalkerYield(walker_yield); @@ -82,7 +82,7 @@ TEST_F(AgentBasicScaleTest, local_and_remote) { (total_v4_routes + num_remote))); //Create a walker and pass callback - Peer *dummy_peer = new Peer(Peer::BGP_PEER, "dummy_peer"); + Peer *dummy_peer = new Peer(Peer::BGP_PEER, "dummy_peer", false); ControllerRouteWalkerTest *route_walker_test = new ControllerRouteWalkerTest(dummy_peer); SetWalkerYield(walker_yield); diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index f4e0e08a0f4..eb285a76fb3 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -425,7 +425,7 @@ VrfEntry *VrfGet(const char *name, bool ret_del) { VrfKey key(name); VrfEntry *vrf = static_cast(agent->vrf_table()->Find(&key, ret_del)); - if (ret_del == false && vrf->IsDeleted()) + if (vrf && (ret_del == false && vrf->IsDeleted())) vrf = NULL; return vrf; From d849297da172156b658da638af3de9da48d6dca4 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 21 Oct 2014 01:47:55 -0700 Subject: [PATCH 014/218] Support to withdraw route on ovsdb notification replace printf with OVSDB_TRACE. --- .../ovsdb_client/logical_switch_ovsdb.cc | 16 ++++++++-------- .../ovsdb_client/ovsdb_client_idl.cc | 7 ------- .../ovsdb_client/ovsdb_client_idl.h | 6 ------ .../ovsdb_client/physical_port_ovsdb.cc | 10 +++++----- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 4 +++- .../ovsdb_client/vlan_port_binding_ovsdb.cc | 10 ++++++++++ 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index 0be94b6e168..27248b4e51c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -184,14 +184,14 @@ void LogicalSwitchTable::OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op op, entry = static_cast(Find(&key)); } if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of local mcast mac %s, logical switch %s\n", - mac, ls ? ls : ""); + OVSDB_TRACE(Trace, "Delete : Local Mcast MAC" + std::string(mac) + + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = NULL; } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add of local mcast mac %s, logical switch %s\n", - mac, ls ? ls : ""); + OVSDB_TRACE(Trace, "Add : Local Mcast MAC" + std::string(mac) + + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = row; } @@ -210,8 +210,8 @@ void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, entry = static_cast(Find(&key)); } if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of remote mcast mac %s, logical switch %s\n", - mac, ls ? ls : ""); + OVSDB_TRACE(Trace, "Delete : Remote Mcast MAC" + std::string(mac) + + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { if (entry->old_mcast_remote_row_ == row) entry->old_mcast_remote_row_ = NULL; @@ -219,8 +219,8 @@ void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, entry->mcast_remote_row_ = NULL; } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add of remote mcast mac %s, logical switch %s\n", - mac, ls ? ls : ""); + OVSDB_TRACE(Trace, "Add : Remote Mcast MAC" + std::string(mac) + + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = row; if (entry->mcast_remote_row_ != row) { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index fccd15b5f0b..2e582d2dbd2 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -21,9 +21,6 @@ extern "C" { #include #include #include -#if 0 -#include -#endif #include @@ -84,10 +81,6 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, unicast_mac_local_ovsdb_.reset(new UnicastMacLocalOvsdb(this, route_peer())); vrf_ovsdb_.reset(new VrfOvsdbObject(this, (DBTable *)agent->vrf_table())); -#if 0 //TODO - physical_locator_table_.reset(new PhysicalLocatorTable(this, - (DBTable *)agent->nexthop_table())); -#endif } OvsdbClientIdl::~OvsdbClientIdl() { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 9cb838033fc..9a3d15b0bf7 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -76,9 +76,6 @@ class OvsdbClientIdl { PhysicalSwitchTable *physical_switch_table() {return physical_switch_table_.get();} LogicalSwitchTable *logical_switch_table() {return logical_switch_table_.get();} PhysicalPortTable *physical_port_table() {return physical_port_table_.get();} -#if 0 //TODO - PhysicalLocatorTable *physical_locator_table() {return physical_locator_table_.get();} -#endif private: friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); friend void ovsdb_wrapper_idl_txn_ack(void *, struct ovsdb_idl_txn *); @@ -96,9 +93,6 @@ class OvsdbClientIdl { std::auto_ptr vlan_port_table_; std::auto_ptr unicast_mac_local_ovsdb_; std::auto_ptr vrf_ovsdb_; -#if 0 //TODO - std::auto_ptr physical_locator_table_; -#endif DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl); }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc index 578d88b60c2..00ac7d6cf99 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -7,6 +7,7 @@ extern "C" { }; #include #include +#include using OVSDB::PhysicalPortEntry; using OVSDB::PhysicalPortTable; @@ -94,20 +95,19 @@ void PhysicalPortTable::Notify(OvsdbClientIdl::Op op, bool override_ovs = false; PhysicalPortEntry *entry = NULL; if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Physical Port %s\n", - ovsdb_wrapper_physical_port_name(row)); + OVSDB_TRACE(Trace, "Delete of Physical Port " + + std::string(ovsdb_wrapper_physical_port_name(row))); PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); entry = static_cast(Find(&key)); if (entry != NULL) { - // TODO trigger notify delete for bindings Delete(entry); } } else if (op == OvsdbClientIdl::OVSDB_ADD) { PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); entry = static_cast(Find(&key)); if (entry == NULL) { - printf("Add/Change of Physical Port %s\n", - ovsdb_wrapper_physical_port_name(row)); + OVSDB_TRACE(Trace, "Add/Change of Physical Port " + + std::string(ovsdb_wrapper_physical_port_name(row))); entry = static_cast(Create(&key)); entry->ovs_entry_ = row; } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index 934a9c7ef9e..6f955c2f454 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -45,7 +45,9 @@ void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op, dest = Ip4Address::from_string(dest_ip, err); } if (op == OvsdbClientIdl::OVSDB_DEL || delete_entry) { - //TODO delete function not available in ovs peer + OVSDB_TRACE(Trace, string("Deleting Route ") + string(mac_str) + + string(" VN uuid ") + string(ls_name)); + peer_->DeleteOvsRoute(ls_uuid, mac); } else if (op == OvsdbClientIdl::OVSDB_ADD) { OVSDB_TRACE(Trace, string("Adding Route ") + string(mac_str) + string(" VN uuid ") + string(ls_name) + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index fffbede5d2f..c24d270020f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include using OVSDB::OvsdbDBEntry; using OVSDB::VlanPortBindingEntry; @@ -53,7 +54,12 @@ void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) { logical_switch_ = l_table->GetReference(&ls_key); port->AddBinding(vlan_, static_cast(logical_switch_.get())); + OVSDB_TRACE(Trace, "Adding port vlan binding port " + + physical_port_name_ + " vlan " + integerToString(vlan_) + + " to Logical Switch " + logical_switch_name_); } else { + OVSDB_TRACE(Trace, "Deleting port vlan binding port " + + physical_port_name_ + " vlan " + integerToString(vlan_)); port->DeleteBinding(vlan_, NULL); } port->Encode(txn); @@ -62,6 +68,8 @@ void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) { void VlanPortBindingEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { PhysicalPortEntry *port = static_cast(physical_port_.get()); + OVSDB_TRACE(Trace, "Deleting port vlan binding port " + + physical_port_name_ + " vlan " + integerToString(vlan_)); port->DeleteBinding(vlan_, static_cast(logical_switch_.get())); logical_switch_ = NULL; @@ -75,6 +83,8 @@ void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { } PhysicalPortEntry *port = static_cast(physical_port_.get()); + OVSDB_TRACE(Trace, "Deleting port vlan binding port " + + physical_port_name_ + " vlan " + integerToString(vlan_)); port->DeleteBinding(vlan_, static_cast(logical_switch_.get())); physical_port_ = NULL; From edacc1ca8e5fd4f1c227f804cccf744521559065 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Tue, 21 Oct 2014 16:42:03 +0530 Subject: [PATCH 015/218] Fix parsing of MAC address in retract string. Issue: ------ The retract string bgp for EVPN routes is of format, -, The current code for marsing mac-address only strips vn-id and tries to decode MAC address from string ,. The decode fails due to presence of IP address. Fix: --- Strip the IP address and additional "," using strtok_r and parse the MAC address --- src/vnsw/agent/controller/controller_peer.cc | 28 ++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index ae3020f2cc8..92ba69995cb 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -123,14 +123,32 @@ void AgentXmppChannel::ReceiveEvpnUpdate(XmlPugi *pugi) { CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name, "EVPN Delete Node id:" + id); - char *mac_str = - strtok_r(const_cast(id.c_str()), "-", &saveptr); + char buff[id.length() + 1]; + uint16_t offset = 0; + strcpy(buff, id.c_str()); + + char *mac_str = strtok_r(buff + offset, "-", &saveptr); uint32_t ethernet_tag = 0; - if (strlen(saveptr) != 0) { + if (mac_str) { ethernet_tag = atoi(mac_str); - mac_str = saveptr; + offset += strlen(mac_str) + 1; } - MacAddress mac(mac_str); + + mac_str = strtok_r(buff + offset, ",", &saveptr); + if (mac_str == NULL) { + CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name, + "Error parsing MAC from retract-id: " +id); + continue; + } + + boost::system::error_code ec; + MacAddress mac(mac_str, &ec); + if (ec) { + CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name, + "Error decoding MAC from retract-id: "+id); + continue; + } + if (mac == MacAddress::BroadcastMac()) { //Deletes the peer path for all boradcast and //traverses the subnet route in VRF to issue delete of peer From 5c33b528b5750b81c879876913db1f4018c80cfd Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 21 Oct 2014 05:02:41 -0700 Subject: [PATCH 016/218] Handling unicast route to reuse physical locator. Separating OvsdbClientSession to separate file. Adding some more traces. Re-try on add failures from ovsdb. --- .../ovs_tor_agent/ovsdb_client/SConscript | 3 +- .../ovsdb_client/ovsdb_client_idl.cc | 28 ++++ .../ovsdb_client/ovsdb_client_idl.h | 42 ++---- .../ovsdb_client/ovsdb_client_session.cc | 38 ++++++ .../ovsdb_client/ovsdb_client_session.h | 38 ++++++ .../ovsdb_client/ovsdb_client_tcp.h | 1 + .../ovs_tor_agent/ovsdb_client/ovsdb_entry.cc | 4 +- .../ovs_tor_agent/ovsdb_client/ovsdb_entry.h | 1 + .../ovsdb_client/ovsdb_wrapper.c | 12 +- .../ovsdb_client/ovsdb_wrapper.h | 3 +- .../ovsdb_client/physical_locator_ovsdb.cc | 122 ++++-------------- .../ovsdb_client/physical_locator_ovsdb.h | 41 +++--- .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 21 ++- 13 files changed, 186 insertions(+), 168 deletions(-) create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index ff8373e8464..dfe7b794fa4 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -25,6 +25,7 @@ libovsdbclient = env.Library('ovsdbclient', 'ovsdb_wrapper.c', 'ovsdb_client.cc', 'ovsdb_client_idl.cc', + 'ovsdb_client_session.cc', 'ovsdb_client_tcp.cc', 'ovsdb_entry.cc', 'ovsdb_object.cc', @@ -34,7 +35,7 @@ libovsdbclient = env.Library('ovsdbclient', 'logical_switch_ovsdb.cc', 'physical_port_ovsdb.cc', 'vlan_port_binding_ovsdb.cc', - # 'physical_locator_ovsdb.cc', + 'physical_locator_ovsdb.cc', 'unicast_mac_local_ovsdb.cc', 'unicast_mac_remote_ovsdb.cc', ]) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 2e582d2dbd2..ff123297f11 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -13,11 +13,13 @@ extern "C" { #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -36,6 +38,10 @@ class PhysicalDeviceVnTable; using OVSDB::OvsdbClientIdl; using OVSDB::OvsdbClientSession; using OVSDB::OvsdbEntryBase; +using OVSDB::PhysicalSwitchTable; +using OVSDB::LogicalSwitchTable; +using OVSDB::PhysicalPortTable; +using OVSDB::PhysicalLocatorTable; namespace OVSDB { void ovsdb_wrapper_idl_callback(void *idl_base, int op, @@ -76,6 +82,7 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, logical_switch_table_.reset(new LogicalSwitchTable(this, (DBTable *)agent->device_manager()->physical_device_vn_table())); physical_port_table_.reset(new PhysicalPortTable(this)); + physical_locator_table_.reset(new PhysicalLocatorTable(this)); vlan_port_table_.reset(new VlanPortBindingTable(this, (DBTable *)agent->device_manager()->logical_port_table())); unicast_mac_local_ovsdb_.reset(new UnicastMacLocalOvsdb(this, @@ -88,6 +95,7 @@ OvsdbClientIdl::~OvsdbClientIdl() { } void OvsdbClientIdl::SendMointorReq() { + OVSDB_TRACE(Trace, "Sending Monitor Request"); SendJsonRpc(ovsdb_wrapper_idl_encode_monitor_request(idl_)); } @@ -148,3 +156,23 @@ Ip4Address OvsdbClientIdl::tsn_ip() { return session_->tsn_ip(); } +OvsPeer *OvsdbClientIdl::route_peer() { + return route_peer_.get(); +} + +PhysicalSwitchTable *OvsdbClientIdl::physical_switch_table() { + return physical_switch_table_.get(); +} + +LogicalSwitchTable *OvsdbClientIdl::logical_switch_table() { + return logical_switch_table_.get(); +} + +PhysicalPortTable *OvsdbClientIdl::physical_port_table() { + return physical_port_table_.get(); +} + +PhysicalLocatorTable *OvsdbClientIdl::physical_locator_table() { + return physical_locator_table_.get(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 9a3d15b0bf7..8f18127006f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -25,6 +25,7 @@ class OvsdbClientSession; class PhysicalSwitchTable; class LogicalSwitchTable; class PhysicalPortTable; +class PhysicalLocatorTable; class VlanPortBindingTable; class PhysicalLocatorTable; class UnicastMacLocalOvsdb; @@ -72,10 +73,12 @@ class OvsdbClientIdl { // Get TOR Service Node IP Ip4Address tsn_ip(); - OvsPeer *route_peer() {return route_peer_.get();} - PhysicalSwitchTable *physical_switch_table() {return physical_switch_table_.get();} - LogicalSwitchTable *logical_switch_table() {return logical_switch_table_.get();} - PhysicalPortTable *physical_port_table() {return physical_port_table_.get();} + OvsPeer *route_peer(); + PhysicalSwitchTable *physical_switch_table(); + LogicalSwitchTable *logical_switch_table(); + PhysicalPortTable *physical_port_table(); + PhysicalLocatorTable *physical_locator_table(); + private: friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); friend void ovsdb_wrapper_idl_txn_ack(void *, struct ovsdb_idl_txn *); @@ -90,38 +93,13 @@ class OvsdbClientIdl { std::auto_ptr physical_switch_table_; std::auto_ptr logical_switch_table_; std::auto_ptr physical_port_table_; + std::auto_ptr physical_locator_table_; std::auto_ptr vlan_port_table_; std::auto_ptr unicast_mac_local_ovsdb_; std::auto_ptr vrf_ovsdb_; DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl); }; +}; // namespace OVSDB -class OvsdbClientSession { -public: - OvsdbClientSession(Agent *agent, OvsPeerManager *manager) : - client_idl_(this, agent, manager), agent_(agent) {} - virtual ~OvsdbClientSession() {} - - virtual Ip4Address tsn_ip() = 0; - virtual void SendMsg(u_int8_t *buf, std::size_t len) = 0; - void MessageProcess(const u_int8_t *buf, std::size_t len) { - client_idl_.MessageProcess(buf, len); - } - - void OnEstablish() { - client_idl_.SendMointorReq(); - } - - void OnClose() { - assert(0); - } -private: - friend class OvsdbClientIdl; - OvsdbClientIdl client_idl_; - Agent *agent_; - DISALLOW_COPY_AND_ASSIGN(OvsdbClientSession); -}; -}; - -#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_IDL_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc new file mode 100644 index 00000000000..2e967598344 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +using OVSDB::OvsdbClientSession; + +OvsdbClientSession::OvsdbClientSession(Agent *agent, OvsPeerManager *manager) : + client_idl_(this, agent, manager), agent_(agent) { +} + +OvsdbClientSession::~OvsdbClientSession() { +} + +void OvsdbClientSession::MessageProcess(const u_int8_t *buf, std::size_t len) { + client_idl_.MessageProcess(buf, len); +} + +void OvsdbClientSession::OnEstablish() { + OVSDB_TRACE(Trace, "Connection to client established"); + client_idl_.SendMointorReq(); +} + +void OvsdbClientSession::OnClose() { + OVSDB_TRACE(Trace, "Connection to client Closed"); + assert(0); +} + + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h new file mode 100644 index 00000000000..ce492de5296 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_SESSION_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_SESSION_H_ + +#include + +#include +#include + +class OvsPeer; +class OvsPeerManager; + +namespace OVSDB { +class OvsdbClientIdl; +class OvsdbClientSession { +public: + OvsdbClientSession(Agent *agent, OvsPeerManager *manager); + virtual ~OvsdbClientSession(); + + virtual Ip4Address tsn_ip() = 0; + virtual void SendMsg(u_int8_t *buf, std::size_t len) = 0; + void MessageProcess(const u_int8_t *buf, std::size_t len); + void OnEstablish(); + void OnClose(); + +private: + friend class OvsdbClientIdl; + OvsdbClientIdl client_idl_; + Agent *agent_; + DISALLOW_COPY_AND_ASSIGN(OvsdbClientSession); +}; +}; // namespace OVSDB + +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_CLIENT_SESSION_H_ + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h index 759ddd08a1b..a8d4533eff7 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -14,6 +14,7 @@ #include #include #include +#include namespace OVSDB { class OvsdbClientTcpSessionReader : public TcpMessageReader { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc index f6ea687d5f1..1cfb02a86ee 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc @@ -139,8 +139,8 @@ void OvsdbDBEntry::Ack(bool success) { object->NotifyEvent(this, KSyncEntry::DEL_ACK); } else if (IsAddChangeAckWaiting()) { OVSDB_TRACE(Error, "Add Transaction failed for " + ToString()); - object->NotifyEvent(this, KSyncEntry::ADD_ACK); - //Add(); + //object->NotifyEvent(this, KSyncEntry::ADD_ACK); + Add(); } else { OVSDB_TRACE(Error, "Ovsdb Delete Transaction failed for " + ToString()); object->OvsdbNotify(OvsdbClientIdl::OVSDB_ADD, ovs_entry_); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h index fba0a523bc9..7ed8f01c3d1 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h @@ -31,6 +31,7 @@ class OvsdbEntry : public KSyncEntry, public OvsdbEntryBase { bool Change(); bool Delete(); + struct ovsdb_idl_row *ovs_entry() {return ovs_entry_;} KSyncObject* GetObject(); void Ack(bool success); protected: diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index ba54413d7b4..25687333164 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -351,7 +351,7 @@ ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row) /* unicast mac remote */ void obvsdb_wrapper_add_ucast_mac_remote(struct ovsdb_idl_txn *txn, const char *mac, - struct ovsdb_idl_row *ls, const char *dest_ip) + struct ovsdb_idl_row *ls, struct ovsdb_idl_row *pl, const char *dest_ip) { struct vteprec_ucast_macs_remote *ucast = vteprec_ucast_macs_remote_insert(txn); @@ -359,9 +359,13 @@ obvsdb_wrapper_add_ucast_mac_remote(struct ovsdb_idl_txn *txn, const char *mac, struct vteprec_logical_switch *l_switch = ls? CONTAINER_OF(ls, struct vteprec_logical_switch, header_) : NULL; vteprec_ucast_macs_remote_set_logical_switch(ucast, l_switch); - struct vteprec_physical_locator *p = vteprec_physical_locator_insert(txn); - vteprec_physical_locator_set_dst_ip(p, dest_ip); - vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + struct vteprec_physical_locator *p = + pl ? CONTAINER_OF(pl, struct vteprec_physical_locator, header_) : NULL; + if (p == NULL) { + p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dest_ip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + } vteprec_ucast_macs_remote_set_locator(ucast, p); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index e799ba4c927..6bd01f3cd1e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -74,7 +74,8 @@ char *ovsdb_wrapper_ucast_mac_local_dst_ip(struct ovsdb_idl_row *row); /* unicast mac remote */ void obvsdb_wrapper_add_ucast_mac_remote(struct ovsdb_idl_txn *txn, - const char *mac, struct ovsdb_idl_row *ls, const char *dest_ip); + const char *mac, struct ovsdb_idl_row *ls, struct ovsdb_idl_row *pl, + const char *dest_ip); void ovsdb_wrapper_delete_ucast_mac_remote(struct ovsdb_idl_row *row); char *ovsdb_wrapper_ucast_mac_remote_mac(struct ovsdb_idl_row *row); char *ovsdb_wrapper_ucast_mac_remote_ip(struct ovsdb_idl_row *row); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc index eca1a644559..7143b80a1be 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc @@ -3,105 +3,35 @@ */ extern "C" { -#include +#include }; -#include +#include #include +#include -#include -#include -#include -#include - -using namespace AGENT; - -PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, - const char *dip_str) : OvsdbDBEntry(table), dip_(dip_str), - is_vxlan_nh_(true), nh_(NULL) { -} +using OVSDB::PhysicalLocatorTable; +using OVSDB::PhysicalLocatorEntry; PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, - const PhysicalLocatorEntry *key) : OvsdbDBEntry(table), dip_(key->dip_), - is_vxlan_nh_(key->is_vxlan_nh_), nh_(key->nh_) { -} - -PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, - const NextHop *entry) : OvsdbDBEntry(table), dip_(""), - is_vxlan_nh_(false), nh_(entry) { - if (entry->GetType() == NextHop::TUNNEL) { - const TunnelNH *tunnel_nh = static_cast(entry); - if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { - dip_ = tunnel_nh->GetDip()->to_string(); - is_vxlan_nh_ = true; - } - } -} - -PhysicalLocatorEntry::PhysicalLocatorEntry(PhysicalLocatorTable *table, - struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry), dip_(""), - is_vxlan_nh_(true), nh_(NULL) { + const std::string &dip_str) : OvsdbEntry(table), dip_(dip_str) { } PhysicalLocatorEntry::~PhysicalLocatorEntry() { } -void PhysicalLocatorEntry::AddMsg(struct ovsdb_idl_txn *txn) { - if (!is_vxlan_nh_) - return; - ovsdb_wrapper_add_physical_locator(txn, ovs_entry_, dip_.c_str()); -} - -void PhysicalLocatorEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { - AddMsg(txn); -} - -void PhysicalLocatorEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { - if (!is_vxlan_nh_) - return; - ovsdb_wrapper_delete_physical_locator(ovs_entry_); -} - -bool PhysicalLocatorEntry::Sync(DBEntry *db_entry) { - NextHop *entry = static_cast(db_entry); - if (entry->GetType() == NextHop::TUNNEL) { - TunnelNH *tunnel_nh = static_cast(entry); - if (tunnel_nh->GetTunnelType().GetType() == TunnelType::VXLAN) { - if (dip_ != tunnel_nh->GetDip()->to_string()) { - // We don't handle dest ip change; - assert(0); - } - } - } - return false; -} - bool PhysicalLocatorEntry::IsLess(const KSyncEntry &entry) const { const PhysicalLocatorEntry &pl_entry = static_cast(entry); - if (is_vxlan_nh_ != pl_entry.is_vxlan_nh_) { - return (is_vxlan_nh_ < pl_entry.is_vxlan_nh_); - } else if (!is_vxlan_nh_) { - return nh_ < pl_entry.nh_; - } return (dip_ < pl_entry.dip_); } KSyncEntry *PhysicalLocatorEntry::UnresolvedReference() { -#if 0 - PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); - PhysicalSwitchEntry key(p_table, device_name_.c_str()); - PhysicalSwitchEntry *p_switch = - static_cast(p_table->GetReference(&key)); - if (!p_switch->IsResolved()) { - return p_switch; - } -#endif return NULL; } -PhysicalLocatorTable::PhysicalLocatorTable(OvsdbClientIdl *idl, - DBTable *table) : OvsdbDBObject(idl, table) { +PhysicalLocatorTable::PhysicalLocatorTable(OvsdbClientIdl *idl) : + OvsdbObject(idl) { idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_LOCATOR, boost::bind(&PhysicalLocatorTable::OvsdbNotify, this, _1, _2)); } @@ -112,16 +42,22 @@ PhysicalLocatorTable::~PhysicalLocatorTable() { void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { + const char *dip_str = ovsdb_wrapper_physical_locator_dst_ip(row); + PhysicalLocatorEntry key(this, dip_str); + PhysicalLocatorEntry *entry = + static_cast(Find(&key)); if (op == OvsdbClientIdl::OVSDB_DEL) { - printf("Delete of Physical Locator %s\n", - ovsdb_wrapper_physical_locator_dst_ip(row)); - //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); - //NotifyDelete((OvsdbDBEntry*)&key); + if (entry != NULL) { + OVSDB_TRACE(Trace, "Delete received for Physical Locator " + + entry->dip_); + Delete(entry); + } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - printf("Add/Change of Physical Locator %s\n", - ovsdb_wrapper_physical_locator_dst_ip(row)); - //PhysicalLocatorEntry key(this, ovsdb_wrapper_physical_locator_dst_ip(row)); - //NotifyAdd((OvsdbDBEntry*)&key, row); + if (entry == NULL) { + entry = static_cast(Create(&key)); + OVSDB_TRACE(Trace, "Add received for Physical Locator " + + entry->dip_); + } } else { assert(0); } @@ -130,19 +66,7 @@ void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, KSyncEntry *PhysicalLocatorTable::Alloc(const KSyncEntry *key, uint32_t index) { const PhysicalLocatorEntry *k_entry = static_cast(key); - PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, k_entry); + PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, k_entry->dip_); return entry; } -KSyncEntry *PhysicalLocatorTable::DBToKSyncEntry(const DBEntry* db_entry) { - const NextHop *entry = - static_cast(db_entry); - PhysicalLocatorEntry *key = new PhysicalLocatorEntry(this, entry); - return static_cast(key); -} - -OvsdbDBEntry *PhysicalLocatorTable::AllocOvsEntry(struct ovsdb_idl_row *row) { - PhysicalLocatorEntry *entry = new PhysicalLocatorEntry(this, row); - return static_cast(entry); -} - diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h index 49485a8d419..6370c087182 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.h @@ -2,52 +2,41 @@ * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ -#ifndef __PHYSICAL_LOCATOR_OVSDB_H__ -#define __PHYSICAL_LOCATOR_OVSDB_H__ +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_LOCATOR_OVSDB_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_LOCATOR_OVSDB_H_ -#include +#include +#include -class KSyncEntry; -class OvsdbDBEntry; -class PhysicalLocatorEntry; - -class PhysicalLocatorTable : public OvsdbDBObject { +namespace OVSDB { +class PhysicalLocatorTable : public OvsdbObject { public: - PhysicalLocatorTable(OvsdbClientIdl *idl, DBTable *table); + PhysicalLocatorTable(OvsdbClientIdl *idl); virtual ~PhysicalLocatorTable(); void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); - KSyncEntry *DBToKSyncEntry(const DBEntry*); - OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); + private: - friend class PhysicalLocatorEntry; DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorTable); }; -class PhysicalLocatorEntry : public OvsdbDBEntry { +class PhysicalLocatorEntry : public OvsdbEntry { public: - PhysicalLocatorEntry(PhysicalLocatorTable *table, const char *dip_str); PhysicalLocatorEntry(PhysicalLocatorTable *table, - const PhysicalLocatorEntry *key); - PhysicalLocatorEntry(PhysicalLocatorTable *table, const NextHop *entry); - PhysicalLocatorEntry(PhysicalLocatorTable *table, struct ovsdb_idl_row *entry); - ~PhysicalLocatorEntry(); - - void AddMsg(struct ovsdb_idl_txn *); - void ChangeMsg(struct ovsdb_idl_txn *); - void DeleteMsg(struct ovsdb_idl_txn *); - bool Sync(DBEntry*); + const std::string &dip_str); + virtual ~PhysicalLocatorEntry(); + bool IsLess(const KSyncEntry&) const; std::string ToString() const {return "Physical Locator";} KSyncEntry* UnresolvedReference(); private: + friend class PhysicalLocatorTable; std::string dip_; - bool is_vxlan_nh_; - const NextHop *nh_; DISALLOW_COPY_AND_ASSIGN(PhysicalLocatorEntry); }; +}; // namespace OVSDB -#endif //__PHYSICAL_LOCATOR_OVSDB_H__ +#endif // SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_PHYSICAL_LOCATOR_OVSDB_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index 292ccdc5a72..03ca66e4621 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -7,6 +7,7 @@ extern "C" { }; #include #include +#include #include #include @@ -62,8 +63,20 @@ void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { static_cast(l_table->GetReference(&key)); logical_switch_ = logical_switch; if (ovs_entry_ == NULL && !dest_ip_.empty()) { + PhysicalLocatorTable *pl_table = + table_->client_idl()->physical_locator_table(); + PhysicalLocatorEntry pl_key(pl_table, dest_ip_); + /* + * we don't take reference to physical locator, just use if locator + * is existing or we will create a new one. + */ + PhysicalLocatorEntry *pl_entry = + static_cast(pl_table->Find(&pl_key)); + struct ovsdb_idl_row *pl_row = NULL; + if (pl_entry) + pl_row = pl_entry->ovs_entry(); obvsdb_wrapper_add_ucast_mac_remote(txn, mac_.c_str(), - logical_switch->ovs_entry(), dest_ip_.c_str()); + logical_switch->ovs_entry(), pl_row, dest_ip_.c_str()); SendTrace(UnicastMacRemoteEntry::ADD_REQ); } } @@ -74,8 +87,10 @@ void UnicastMacRemoteEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { void UnicastMacRemoteEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { logical_switch_ = NULL; - ovsdb_wrapper_delete_ucast_mac_remote(ovs_entry_); - SendTrace(UnicastMacRemoteEntry::DEL_REQ); + if (ovs_entry_) { + ovsdb_wrapper_delete_ucast_mac_remote(ovs_entry_); + SendTrace(UnicastMacRemoteEntry::DEL_REQ); + } } void UnicastMacRemoteEntry::OvsdbChange() { From bf05f9dec6660c157ce207cc801ca5aecb3099e4 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Tue, 21 Oct 2014 18:46:18 -0700 Subject: [PATCH 017/218] TSN agent changes for OVS. 1) DHCP handling - reply to dhcp request from baremetals behind TOR, IP-MAC binding received from VMI created for baremetal. 2) Multicast TOR and subscribe for multicast fabric tree when TOR is added (even in absence of any local vm interface) 3) VM interface creation binded to TOR logical ports. --- src/ksync/ksync_sock_user.cc | 10 +- src/vnsw/agent/SConscript | 7 +- src/vnsw/agent/cfg/cfg_interface_listener.cc | 5 +- src/vnsw/agent/cmn/agent.cc | 16 +- src/vnsw/agent/cmn/agent.h | 16 + src/vnsw/agent/contrail/SConscript | 2 + .../agent/contrail/contrail_agent_init.cc | 1 - src/vnsw/agent/contrail/contrail_agent_init.h | 1 + .../agent/controller/controller_export.cc | 15 +- src/vnsw/agent/init/agent_init.cc | 20 +- src/vnsw/agent/init/agent_init.h | 2 + src/vnsw/agent/init/agent_param.cc | 29 +- src/vnsw/agent/init/agent_param.h | 13 +- src/vnsw/agent/kstate/kstate.cc | 4 +- src/vnsw/agent/kstate/kstate.sandesh | 8 +- src/vnsw/agent/kstate/nh_kstate.cc | 18 - .../agent/kstate/test/test_sandesh_kstate.cc | 18 +- src/vnsw/agent/kstate/vrf_stats_kstate.cc | 14 - src/vnsw/agent/ksync/interface_ksync.cc | 10 + src/vnsw/agent/ksync/interface_ksync.h | 1 + src/vnsw/agent/ksync/nexthop_ksync.cc | 2 - src/vnsw/agent/ksync/route_ksync.cc | 37 +-- src/vnsw/agent/ksync/route_ksync.h | 4 +- src/vnsw/agent/oper/agent.sandesh | 3 + src/vnsw/agent/oper/agent_route.cc | 177 ++++++++++ src/vnsw/agent/oper/agent_route.h | 1 + src/vnsw/agent/oper/inet_unicast_route.cc | 14 + src/vnsw/agent/oper/layer2_route.cc | 161 +-------- src/vnsw/agent/oper/layer2_route.h | 8 +- src/vnsw/agent/oper/multicast.cc | 207 +++++++++++- src/vnsw/agent/oper/multicast.h | 31 +- src/vnsw/agent/oper/peer.h | 4 +- src/vnsw/agent/oper/vm.cc | 2 + src/vnsw/agent/oper/vm_interface.cc | 307 ++++++++++++------ src/vnsw/agent/oper/vm_interface.h | 101 +++--- src/vnsw/agent/oper/vn.cc | 60 +++- src/vnsw/agent/oper/vn.h | 13 +- src/vnsw/agent/physical_devices/SConscript | 2 + .../physical_devices/tables/device_manager.cc | 4 + .../physical_devices/tables/device_manager.h | 2 + .../tables/physical_device.cc | 5 + src/vnsw/agent/pkt/pkt_handler.cc | 144 +++++++- src/vnsw/agent/pkt/pkt_handler.h | 17 + src/vnsw/agent/pkt/pkt_init.cc | 3 + src/vnsw/agent/services/dhcp_handler.cc | 21 +- src/vnsw/agent/services/dhcpv6_handler.cc | 20 +- src/vnsw/agent/services/dns_handler.cc | 9 +- src/vnsw/agent/services/icmp_handler.cc | 9 +- src/vnsw/agent/services/test/dhcp_test.cc | 206 ++++++++++++ src/vnsw/agent/uve/agent_stats_collector.cc | 1 - .../agent/uve/agent_stats_sandesh_context.cc | 20 +- 51 files changed, 1341 insertions(+), 464 deletions(-) diff --git a/src/ksync/ksync_sock_user.cc b/src/ksync/ksync_sock_user.cc index 80bac85522a..350cbea05a0 100644 --- a/src/ksync/ksync_sock_user.cc +++ b/src/ksync/ksync_sock_user.cc @@ -298,7 +298,7 @@ void KSyncSockTypeMap::VrfStatsAdd(int vrf_id) { vr_vrf_stats_req vrf_stats; vrf_stats.set_vsr_vrf(vrf_id); vrf_stats.set_vsr_family(AF_INET); - vrf_stats.set_vsr_type(RT_UCAST); + //vrf_stats.set_vsr_type(RT_UCAST); vrf_stats.set_vsr_rid(0); vrf_stats.set_vsr_discards(0); vrf_stats.set_vsr_resolves(0); @@ -308,9 +308,9 @@ void KSyncSockTypeMap::VrfStatsAdd(int vrf_id) { vrf_stats.set_vsr_gre_mpls_tunnels(0); vrf_stats.set_vsr_ecmp_composites(0); vrf_stats.set_vsr_fabric_composites(0); - vrf_stats.set_vsr_l3_mcast_composites(0); + //vrf_stats.set_vsr_l3_mcast_composites(0); vrf_stats.set_vsr_l2_mcast_composites(0); - vrf_stats.set_vsr_multi_proto_composites(0); + //vrf_stats.set_vsr_multi_proto_composites(0); vrf_stats.set_vsr_encaps(0); vrf_stats.set_vsr_l2_encaps(0); @@ -349,9 +349,9 @@ void KSyncSockTypeMap::VrfStatsUpdate(int vrf_id, uint64_t discards, uint64_t re vrf_stats.set_vsr_gre_mpls_tunnels(gre_mpls_tunnels); vrf_stats.set_vsr_ecmp_composites(ecmp_composites); vrf_stats.set_vsr_fabric_composites(fabric_composites); - vrf_stats.set_vsr_l3_mcast_composites(l3_mcast_composites); + //vrf_stats.set_vsr_l3_mcast_composites(l3_mcast_composites); vrf_stats.set_vsr_l2_mcast_composites(l2_mcast_composites); - vrf_stats.set_vsr_multi_proto_composites(multi_proto_composites); + //vrf_stats.set_vsr_multi_proto_composites(multi_proto_composites); vrf_stats.set_vsr_encaps(encaps); vrf_stats.set_vsr_l2_encaps(l2_encaps); } diff --git a/src/vnsw/agent/SConscript b/src/vnsw/agent/SConscript index 9da8bde9a7c..67f29cfc02c 100644 --- a/src/vnsw/agent/SConscript +++ b/src/vnsw/agent/SConscript @@ -84,6 +84,8 @@ env.Append(LIBPATH = MapBuildDir([ 'vnsw/agent/oper', 'vnsw/agent/pkt', 'vnsw/agent/services', + 'vnsw/agent/physical_devices/tables', + 'vnsw/agent/physical_devices/tsn', 'vnsw/agent/uve', 'vnsw/agent/vgw', 'vrouter/utils', @@ -143,6 +145,8 @@ env.Prepend(LIBS = [ 'ksync', 'nova_ins', 'nova_ins_thrift', + 'physical_devices', + 'tsn', 'vgw', ]) @@ -290,7 +294,8 @@ subdirs = [ 'ksync', 'openstack', 'oper', - 'physical_devices', + 'physical_devices/tables', + 'physical_devices/tsn', 'pkt', 'services', 'test', diff --git a/src/vnsw/agent/cfg/cfg_interface_listener.cc b/src/vnsw/agent/cfg/cfg_interface_listener.cc index 6c5a557ccc5..fad23c76b3e 100644 --- a/src/vnsw/agent/cfg/cfg_interface_listener.cc +++ b/src/vnsw/agent/cfg/cfg_interface_listener.cc @@ -33,7 +33,7 @@ void InterfaceCfgClient::Notify(DBTablePartBase *partition, DBEntryBase *e) { if (entry->IsDeleted()) { VmInterface::Delete(agent->interface_table(), - entry->GetUuid()); + entry->GetUuid(), VmInterface::EXTERNAL); } else { uint16_t tx_vlan_id = VmInterface::kInvalidVlanId; uint16_t rx_vlan_id = VmInterface::kInvalidVlanId; @@ -48,7 +48,8 @@ void InterfaceCfgClient::Notify(DBTablePartBase *partition, DBEntryBase *e) { entry->GetUuid(), entry->GetIfname(), entry->ip_addr().to_v4(), entry->GetMacAddr(), entry->vm_name(), entry->vm_project_uuid(), - tx_vlan_id, rx_vlan_id, port, entry->ip6_addr()); + tx_vlan_id, rx_vlan_id, port, entry->ip6_addr(), + VmInterface::EXTERNAL); IFMapNode *node = UuidToIFNode(entry->GetUuid()); if (node != NULL) { DBRequest req; diff --git a/src/vnsw/agent/cmn/agent.cc b/src/vnsw/agent/cmn/agent.cc index b655198c966..c2005baccef 100644 --- a/src/vnsw/agent/cmn/agent.cc +++ b/src/vnsw/agent/cmn/agent.cc @@ -182,6 +182,14 @@ void Agent::CopyConfig(AgentParam *params) { int count = 0; int dns_count = 0; + if (params_->tsn_ip_1().to_ulong()) { + tsn_ip_1_ = params_->tsn_ip_1().to_string(); + } + + if (params_->tsn_ip_2().to_ulong()) { + tsn_ip_2_ = params_->tsn_ip_2().to_string(); + } + if (params_->xmpp_server_1().to_ulong()) { SetAgentMcastLabelRange(count); xs_addr_[count++] = params_->xmpp_server_1().to_string(); @@ -231,6 +239,7 @@ void Agent::CopyConfig(AgentParam *params) { simulate_evpn_tor_ = params->simulate_evpn_tor(); debug_ = params_->debug(); test_mode_ = params_->test_mode(); + tsn_enabled_ = params_->isTsnEnabled(); } DiscoveryAgentClient *Agent::discovery_client() const { @@ -338,6 +347,8 @@ void Agent::InitPeers() { vgw_peer_.reset(new Peer(Peer::VGW_PEER, VGW_PEER_NAME, true)); multicast_peer_.reset(new Peer(Peer::MULTICAST_PEER, MULTICAST_PEER_NAME, false)); + multicast_tor_peer_.reset(new Peer(Peer::MULTICAST_TOR_PEER, + MULTICAST_TOR_PEER_NAME, false)); multicast_tree_builder_peer_.reset( new Peer(Peer::MULTICAST_FABRIC_TREE_BUILDER, MULTICAST_FABRIC_TREE_BUILDER_NAME, @@ -357,7 +368,8 @@ Agent::Agent() : acl_table_(NULL), mirror_table_(NULL), vrf_assign_table_(NULL), mirror_cfg_table_(NULL), intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL), router_id_(0), prefix_len_(0), - gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(), + gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), + tsn_ip_1_(), tsn_ip_2_(), xs_addr_(), xs_port_(), xs_stime_(), xs_dns_idx_(0), dns_addr_(), dns_port_(), dss_addr_(""), dss_port_(0), dss_xs_instances_(0), discovery_client_name_(), @@ -371,7 +383,7 @@ Agent::Agent() : ksync_sync_mode_(true), mgmt_ip_(""), vxlan_network_identifier_mode_(AUTOMATIC), headless_agent_mode_(false), connection_state_(NULL), debug_(false), test_mode_(false), - init_done_(false), simulate_evpn_tor_(false) { + init_done_(false), simulate_evpn_tor_(false), tsn_enabled_(false) { assert(singleton_ == NULL); singleton_ = this; diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h index 35e576d541c..3bd346a2f17 100644 --- a/src/vnsw/agent/cmn/agent.h +++ b/src/vnsw/agent/cmn/agent.h @@ -375,6 +375,14 @@ class Agent { AgentSignal *agent_signal() const { return agent_signal_.get(); } + const std::string &tsn_ip_1() const { + return tsn_ip_1_; + } + + const std::string &tsn_ip_2() const { + return tsn_ip_2_; + } + // TODO: Should they be moved under controller/dns/cfg? // Common XMPP Client for control-node and config clients @@ -633,6 +641,7 @@ class Agent { const Peer *ecmp_peer() const {return ecmp_peer_.get();} const Peer *vgw_peer() const {return vgw_peer_.get();} const Peer *multicast_peer() const {return multicast_peer_.get();} + const Peer *multicast_tor_peer() const {return multicast_tor_peer_.get();} const Peer *multicast_tree_builder_peer() const { return multicast_tree_builder_peer_.get();} @@ -716,6 +725,9 @@ class Agent { bool simulate_evpn_tor() const {return simulate_evpn_tor_;} void set_simulate_evpn_tor(bool mode) {simulate_evpn_tor_ = mode;} + bool tsn_enabled() const {return tsn_enabled_;} + void set_tsn_enabled(bool val) {tsn_enabled_ = val;} + IFMapAgentParser *ifmap_parser() const {return ifmap_parser_;} void set_ifmap_parser(IFMapAgentParser *parser) { ifmap_parser_ = parser; @@ -833,6 +845,8 @@ class Agent { Ip4Address gateway_id_; std::string xs_cfg_addr_; int8_t xs_idx_; + std::string tsn_ip_1_; + std::string tsn_ip_2_; std::string xs_addr_[MAX_XMPP_SERVERS]; uint32_t xs_port_[MAX_XMPP_SERVERS]; uint64_t xs_stime_[MAX_XMPP_SERVERS]; @@ -863,6 +877,7 @@ class Agent { std::auto_ptr ecmp_peer_; std::auto_ptr vgw_peer_; std::auto_ptr multicast_peer_; + std::auto_ptr multicast_tor_peer_; std::auto_ptr multicast_tree_builder_peer_; std::auto_ptr agent_signal_; @@ -883,6 +898,7 @@ class Agent { bool test_mode_; bool init_done_; bool simulate_evpn_tor_; + bool tsn_enabled_; // Flow information uint32_t flow_table_size_; diff --git a/src/vnsw/agent/contrail/SConscript b/src/vnsw/agent/contrail/SConscript index 73f50e7ef7b..f9cb0d4d869 100644 --- a/src/vnsw/agent/contrail/SConscript +++ b/src/vnsw/agent/contrail/SConscript @@ -69,6 +69,8 @@ buildinfo_dep_libs += MapBuildAgentLib([ 'openstack/libnova_ins_thrift.a', 'oper/libvnswoperdb.a', 'pkt/libpkt.a', 'diag/libdiag.a', + 'physical_devices/tables/libphysical_devices.a', + 'physical_devices/tsn/libtsn.a', 'services/libagent_services.a', 'uve/libagentuve.a' ]) diff --git a/src/vnsw/agent/contrail/contrail_agent_init.cc b/src/vnsw/agent/contrail/contrail_agent_init.cc index ded7a5cc230..847ce2daaa4 100644 --- a/src/vnsw/agent/contrail/contrail_agent_init.cc +++ b/src/vnsw/agent/contrail/contrail_agent_init.cc @@ -50,7 +50,6 @@ void ContrailAgentInit::CreateModules() { ksync_.reset(AgentObjectFactory::Create(agent())); agent()->set_ksync(ksync_.get()); - } void ContrailAgentInit::ConnectToController() { diff --git a/src/vnsw/agent/contrail/contrail_agent_init.h b/src/vnsw/agent/contrail/contrail_agent_init.h index cb96979e532..89ec563f23a 100644 --- a/src/vnsw/agent/contrail/contrail_agent_init.h +++ b/src/vnsw/agent/contrail/contrail_agent_init.h @@ -14,6 +14,7 @@ class AgentParam; class DiagTable; class ServicesModule; class PktModule; +class TsnVrfListener; // The class to drive agent initialization. // Defines control parameters used to enable/disable agent features diff --git a/src/vnsw/agent/controller/controller_export.cc b/src/vnsw/agent/controller/controller_export.cc index 0c901bcc776..b0c6cb0bfc9 100644 --- a/src/vnsw/agent/controller/controller_export.cc +++ b/src/vnsw/agent/controller/controller_export.cc @@ -198,12 +198,22 @@ void RouteExport::UnicastNotify(AgentXmppChannel *bgp_xmpp_peer, } } +static const AgentPath *GetMulticastExportablePath(const Agent *agent, + const AgentRoute *route) { + const AgentPath *active_path = route->FindPath(agent->local_vm_peer()); + //If no loca peer, then look for tor peer as that should also result + //in export of route. + if (active_path == NULL) + active_path = route->FindPath(agent->multicast_tor_peer()); + return active_path; +} + static bool RouteCanDissociate(const AgentRoute *route) { bool can_dissociate = route->IsDeleted(); if (route->is_multicast()) { Agent *agent = static_cast(route->get_table())-> agent(); - const AgentPath *active_path = route->FindPath(agent->local_vm_peer()); + const AgentPath *active_path = GetMulticastExportablePath(agent, route); if (active_path == NULL) return true; const NextHop *nh = active_path ? active_path->nexthop(agent) : NULL; @@ -268,7 +278,6 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, } if (!route_can_be_dissociated) { - if (!(agent->simulate_evpn_tor()) && ((state->exported_ == false) || (state->force_chg_ == true))) { //Sending 255.255.255.255 for fabric tree @@ -283,7 +292,7 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, } //Sending ff:ff:ff:ff:ff:ff for evpn replication - const AgentPath *active_path = route->FindPath(agent->local_vm_peer()); + const AgentPath *active_path = GetMulticastExportablePath(agent, route); //const AgentPath *active_path = route->GetActivePath(); TunnelType::Type old_tunnel_type = state->tunnel_type_; uint32_t old_label = state->label_; diff --git a/src/vnsw/agent/init/agent_init.cc b/src/vnsw/agent/init/agent_init.cc index 6b2914f0384..7862c703a4e 100644 --- a/src/vnsw/agent/init/agent_init.cc +++ b/src/vnsw/agent/init/agent_init.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "agent_init.h" @@ -150,8 +151,13 @@ void AgentInit::CreateModulesBase() { if (enable_controller_) { controller_.reset(new VNController(agent())); + agent_->set_controller(controller_.get()); + } + + if (agent_->tsn_enabled()) { + device_manager_.reset(new PhysicalDeviceManager(agent())); + agent_->set_device_manager(device_manager_.get()); } - agent_->set_controller(controller_.get()); CreateModules(); } @@ -166,6 +172,10 @@ void AgentInit::CreateDBTablesBase() { } CreateDBTables(); + + if (agent_->tsn_enabled()) { + device_manager_->CreateDBTables(agent_->db()); + } } void AgentInit::RegisterDBClientsBase() { @@ -178,6 +188,10 @@ void AgentInit::RegisterDBClientsBase() { } RegisterDBClients(); + + if (agent_->tsn_enabled()) { + device_manager_->RegisterDBClients(); + } } void AgentInit::InitModulesBase() { @@ -190,6 +204,10 @@ void AgentInit::InitModulesBase() { } InitModules(); + + if (agent_->tsn_enabled()) { + device_manager_->Init(); + } } void AgentInit::CreateVrfBase() { diff --git a/src/vnsw/agent/init/agent_init.h b/src/vnsw/agent/init/agent_init.h index 5c18c2c3cf7..504160e5c5f 100644 --- a/src/vnsw/agent/init/agent_init.h +++ b/src/vnsw/agent/init/agent_init.h @@ -13,6 +13,7 @@ class AgentParam; class DiagTable; class ServicesModule; class PktModule; +class PhysicalDeviceManager; // The class to drive agent initialization. Does init of basic modules // Daemons should derive from AgentInit class and tune / implement virtual @@ -161,6 +162,7 @@ class AgentInit { bool enable_controller_; std::auto_ptr controller_; + std::auto_ptr device_manager_; DISALLOW_COPY_AND_ASSIGN(AgentInit); }; diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index 1b06a2fd5a2..41415b4f639 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -442,6 +442,12 @@ void AgentParam::ParseHeadlessMode() { } } +void AgentParam::ParseTsnMode() { + if (!GetValueFromTree(enable_tsn_, "DEFAULT.tsn")) { + enable_tsn_ = false; + } +} + void AgentParam::ParseSimulateEvpnTor() { if (!GetValueFromTree(simulate_evpn_tor_, "DEFAULT.simulate_evpn_tor")) { @@ -588,6 +594,11 @@ void AgentParam::ParseHeadlessModeArguments GetOptValue(var_map, headless_mode_, "DEFAULT.headless_mode"); } +void AgentParam::ParseTsnModeArguments + (const boost::program_options::variables_map &var_map) { + GetOptValue(var_map, enable_tsn_, "DEFAULT.tsn_mode"); +} + void AgentParam::ParseServiceInstanceArguments (const boost::program_options::variables_map &var_map) { GetOptValue(var_map, si_netns_command_, "SERVICE-INSTANCE.netns_command"); @@ -628,6 +639,7 @@ void AgentParam::InitFromConfig() { ParseCollector(); ParseVirtualHost(); + ParseServerList("TSN.server", &tsn_ip_1_, &tsn_ip_2_); ParseServerList("CONTROL-NODE.server", &xmpp_server_1_, &xmpp_server_2_); ParseServerList("DNS.server", &dns_server_1_, &dns_port_1_, &dns_server_2_, &dns_port_2_); @@ -640,6 +652,7 @@ void AgentParam::InitFromConfig() { ParseHeadlessMode(); ParseSimulateEvpnTor(); ParseServiceInstance(); + ParseTsnMode(); cout << "Config file <" << config_file_ << "> parsing completed.\n"; return; } @@ -647,6 +660,8 @@ void AgentParam::InitFromConfig() { void AgentParam::InitFromArguments() { ParseCollectorArguments(var_map_); ParseVirtualHostArguments(var_map_); + ParseServerListArguments(var_map_, tsn_ip_1_, tsn_ip_2_, + "CONTROL-NODE.server"); ParseServerListArguments(var_map_, xmpp_server_1_, xmpp_server_2_, "CONTROL-NODE.server"); ParseServerListArguments(var_map_, &dns_server_1_, &dns_port_1_, @@ -658,6 +673,7 @@ void AgentParam::InitFromArguments() { ParseMetadataProxyArguments(var_map_); ParseHeadlessModeArguments(var_map_); ParseServiceInstanceArguments(var_map_); + ParseTsnModeArguments(var_map_); return; } @@ -847,6 +863,10 @@ void AgentParam::LogConfig() const { LOG(DEBUG, "Vmware mode : Esxi_Neutron"); } } + + if (enable_tsn_) { + LOG(DEBUG, "TSN Agent mode : Enabled"); + } } void AgentParam::set_test_mode(bool mode) { @@ -867,12 +887,15 @@ void AgentParam::ParseArguments(int argc, char *argv[]) { AgentParam::AgentParam(Agent *agent, bool enable_flow_options, bool enable_vhost_options, bool enable_hypervisor_options, - bool enable_service_options) : + bool enable_service_options, + bool enable_tsn) : enable_flow_options_(enable_flow_options), enable_vhost_options_(enable_vhost_options), enable_hypervisor_options_(enable_hypervisor_options), enable_service_options_(enable_service_options), - vhost_(), eth_port_(), xmpp_instance_count_(), xmpp_server_1_(), + enable_tsn_(enable_tsn), tsn_ip_1_(), tsn_ip_2_(), + vhost_(), eth_port_(), + xmpp_instance_count_(), xmpp_server_1_(), xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dns_port_1_(ContrailPorts::DnsServerPort()), dns_port_2_(ContrailPorts::DnsServerPort()), @@ -923,6 +946,8 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, "Sandesh HTTP listener port") ("DEFAULT.tunnel_type", opt::value()->default_value("MPLSoGRE"), "Tunnel Encapsulation type ") + ("DEFAULT.tsn_mode", opt::value(), + "Run compute-node in TSN mode") ("DISCOVERY.server", opt::value(), "IP address of discovery server") ("DISCOVERY.max_control_nodes", opt::value(), diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index e91160db21e..4b2c0b5f91d 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -50,7 +50,8 @@ class AgentParam { AgentParam(Agent *agent, bool enable_flow_options = true, bool enable_vhost_options = true, bool enable_hypervisor_options = true, - bool enable_service_options = true); + bool enable_service_options = true, + bool enable_tsn = false); virtual ~AgentParam(); virtual int Validate(); @@ -75,6 +76,8 @@ class AgentParam { const Ip4Address &xen_ll_gw() const { return xen_ll_.gw_; } const std::string ð_port() const { return eth_port_; } + const Ip4Address &tsn_ip_1() const { return tsn_ip_1_; } + const Ip4Address &tsn_ip_2() const { return tsn_ip_2_; } const Ip4Address &xmpp_server_1() const { return xmpp_server_1_; } const Ip4Address &xmpp_server_2() const { return xmpp_server_2_; } const Ip4Address &dns_server_1() const { return dns_server_1_; } @@ -154,6 +157,8 @@ class AgentParam { boost::program_options::options_description options() const { return options_; } + bool isTsnEnabled() const { return enable_tsn_; } + protected: void set_mode(Mode m) { mode_ = m; } virtual void InitFromSystem(); @@ -204,6 +209,7 @@ class AgentParam { void ParseHeadlessMode(); void ParseSimulateEvpnTor(); void ParseServiceInstance(); + void ParseTsnMode(); void ParseCollectorArguments (const boost::program_options::variables_map &v); @@ -225,6 +231,8 @@ class AgentParam { (const boost::program_options::variables_map &v); void ParseServiceInstanceArguments (const boost::program_options::variables_map &v); + void ParseTsnModeArguments + (const boost::program_options::variables_map &v); boost::program_options::variables_map var_map_; boost::program_options::options_description options_; @@ -232,6 +240,9 @@ class AgentParam { bool enable_vhost_options_; bool enable_hypervisor_options_; bool enable_service_options_; + bool enable_tsn_; + Ip4Address tsn_ip_1_; + Ip4Address tsn_ip_2_; PortInfo vhost_; std::string eth_port_; diff --git a/src/vnsw/agent/kstate/kstate.cc b/src/vnsw/agent/kstate/kstate.cc index 525d2a3bacd..b6bfa45383d 100644 --- a/src/vnsw/agent/kstate/kstate.cc +++ b/src/vnsw/agent/kstate/kstate.cc @@ -301,7 +301,7 @@ void KState::VrfStatsMsgHandler(vr_vrf_stats_req *r) { const_cast&>(resp->get_vrf_stats_list()); data.set_vrf_id(r->get_vsr_vrf()); data.set_vrf_family(state->FamilyToString(r->get_vsr_family())); - data.set_vrf_type(state->TypeToString(r->get_vsr_type())); + //data.set_vrf_type(state->TypeToString(r->get_vsr_type())); data.set_vrf_rid(r->get_vsr_rid()); data.set_vrf_discards(r->get_vsr_discards()); data.set_vrf_resolves(r->get_vsr_resolves()); @@ -309,9 +309,7 @@ void KState::VrfStatsMsgHandler(vr_vrf_stats_req *r) { data.set_vrf_udp_tunnels(r->get_vsr_udp_tunnels()); data.set_vrf_udp_mpls_tunnels(r->get_vsr_udp_mpls_tunnels()); data.set_vrf_gre_mpls_tunnels(r->get_vsr_gre_mpls_tunnels()); - data.set_vrf_l3_mcast_composites(r->get_vsr_l3_mcast_composites()); data.set_vrf_l2_mcast_composites(r->get_vsr_l2_mcast_composites()); - data.set_vrf_multi_proto_composites(r->get_vsr_multi_proto_composites()); data.set_vrf_fabric_composites(r->get_vsr_fabric_composites()); data.set_vrf_ecmp_composites(r->get_vsr_ecmp_composites()); data.set_vrf_encaps(r->get_vsr_encaps()); diff --git a/src/vnsw/agent/kstate/kstate.sandesh b/src/vnsw/agent/kstate/kstate.sandesh index a6bd62def53..38714ca1d50 100644 --- a/src/vnsw/agent/kstate/kstate.sandesh +++ b/src/vnsw/agent/kstate/kstate.sandesh @@ -195,11 +195,9 @@ struct KVrfStatsInfo { 10: i64 vrf_gre_mpls_tunnels; 11: i64 vrf_fabric_composites; 12: i64 vrf_l2_mcast_composites; - 13: i64 vrf_l3_mcast_composites; - 14: i64 vrf_multi_proto_composites; - 15: i64 vrf_ecmp_composites; - 16: i64 vrf_encaps; - 17: i64 vrf_vxlan_tunnels; + 13: i64 vrf_ecmp_composites; + 14: i64 vrf_encaps; + 15: i64 vrf_vxlan_tunnels; } request sandesh KVrfStatsReq { diff --git a/src/vnsw/agent/kstate/nh_kstate.cc b/src/vnsw/agent/kstate/nh_kstate.cc index e7d4bcb97b8..9d7d017fa9c 100644 --- a/src/vnsw/agent/kstate/nh_kstate.cc +++ b/src/vnsw/agent/kstate/nh_kstate.cc @@ -186,15 +186,6 @@ const string NHKState::FlagsToString(short nh_flags) const { } } - if (flags & NH_FLAG_COMPOSITE_MULTI_PROTO) { - if (assigned) { - flag_str.append("| " + multi_proto_multicast); - } else { - flag_str.assign(multi_proto_multicast); - assigned = true; - } - } - if (flags & NH_FLAG_COMPOSITE_L2) { if (assigned) { flag_str.append("| " + l2_multicast); @@ -204,15 +195,6 @@ const string NHKState::FlagsToString(short nh_flags) const { } } - if (flags & NH_FLAG_COMPOSITE_L3) { - if (assigned) { - flag_str.append("| " + l3_multicast); - } else { - flag_str.assign(l3_multicast); - assigned = true; - } - } - if (!assigned) { return "NIL"; } diff --git a/src/vnsw/agent/kstate/test/test_sandesh_kstate.cc b/src/vnsw/agent/kstate/test/test_sandesh_kstate.cc index 3d7eb3675b0..9a5fa0a37ae 100644 --- a/src/vnsw/agent/kstate/test/test_sandesh_kstate.cc +++ b/src/vnsw/agent/kstate/test/test_sandesh_kstate.cc @@ -586,20 +586,10 @@ TEST_F(KStateSandeshTest, NhTest_flags) { flags = NH_FLAG_COMPOSITE_FABRIC; KSyncSockTypeMap::NHAdd(212, flags); - flags = NH_FLAG_VALID|NH_FLAG_COMPOSITE_MULTI_PROTO; - KSyncSockTypeMap::NHAdd(213, flags); - flags = NH_FLAG_COMPOSITE_MULTI_PROTO; - KSyncSockTypeMap::NHAdd(214, flags); - flags = NH_FLAG_VALID|NH_FLAG_COMPOSITE_L2; - KSyncSockTypeMap::NHAdd(215, flags); + KSyncSockTypeMap::NHAdd(213, flags); flags = NH_FLAG_COMPOSITE_L2; - KSyncSockTypeMap::NHAdd(216, flags); - - flags = NH_FLAG_VALID|NH_FLAG_COMPOSITE_L3; - KSyncSockTypeMap::NHAdd(217, flags); - flags = NH_FLAG_COMPOSITE_L3; - KSyncSockTypeMap::NHAdd(218, flags); + KSyncSockTypeMap::NHAdd(214, flags); //Send NH DUMP request ClearCount(); @@ -628,10 +618,6 @@ TEST_F(KStateSandeshTest, NhTest_flags) { KSyncSockTypeMap::NHDelete(212); KSyncSockTypeMap::NHDelete(213); KSyncSockTypeMap::NHDelete(214); - KSyncSockTypeMap::NHDelete(215); - KSyncSockTypeMap::NHDelete(216); - KSyncSockTypeMap::NHDelete(217); - KSyncSockTypeMap::NHDelete(218); } TEST_F(KStateSandeshTest, NhTest_MultiResponse) { diff --git a/src/vnsw/agent/kstate/vrf_stats_kstate.cc b/src/vnsw/agent/kstate/vrf_stats_kstate.cc index fdb53fe972f..f4f50ad473e 100644 --- a/src/vnsw/agent/kstate/vrf_stats_kstate.cc +++ b/src/vnsw/agent/kstate/vrf_stats_kstate.cc @@ -17,7 +17,6 @@ VrfStatsKState::VrfStatsKState(KVrfStatsResp *obj, const std::string &resp_ctx, req.set_h_op(sandesh_op::GET); req.set_vsr_vrf(id); req.set_vsr_family(AF_INET); - req.set_vsr_type(RT_UCAST); } else { InitDumpRequest(req); req.set_vsr_marker(-1); @@ -28,7 +27,6 @@ void VrfStatsKState::InitDumpRequest(vr_vrf_stats_req &req) const { req.set_h_op(sandesh_op::DUMP); req.set_vsr_rid(0); req.set_vsr_family(AF_INET); - req.set_vsr_type(RT_UCAST); } void VrfStatsKState::Handler() { @@ -66,18 +64,6 @@ void VrfStatsKState::SendResponse() { response_object_ = new KVrfStatsResp(); } -const string VrfStatsKState::TypeToString(int vrf_stats_type) const { - unsigned short type = vrf_stats_type; - switch(type) { - case RT_UCAST: - return "RT_UCAST"; - case RT_MCAST: - return "RT_MCAST"; - default: - return "INVALID"; - } -} - const string VrfStatsKState::FamilyToString(int vrf_family) const { unsigned family = vrf_family; switch(family) { diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 358cd75ec70..b6c2d76382c 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -58,6 +58,7 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, parent_(entry->parent_), policy_enabled_(entry->policy_enabled_), sub_type_(entry->sub_type_), + vm_sub_type_(entry->vm_sub_type_), type_(entry->type_), rx_vlan_id_(entry->rx_vlan_id_), tx_vlan_id_(entry->tx_vlan_id_), @@ -89,6 +90,7 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, parent_(NULL), policy_enabled_(false), sub_type_(InetInterface::VHOST), + vm_sub_type_(VmInterface::NONE), type_(intf->type()), rx_vlan_id_(VmInterface::kInvalidVlanId), tx_vlan_id_(VmInterface::kInvalidVlanId), @@ -113,6 +115,7 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, InterfaceKSyncEntry tmp(ksync_obj_, vmitf->parent()); parent_ = ksync_obj_->GetReference(&tmp); } + vm_sub_type_ = vmitf->sub_type(); } else if (type_ == Interface::INET) { const InetInterface *inet_intf = static_cast(intf); @@ -169,6 +172,7 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { if (intf->type() == Interface::VM_INTERFACE) { VmInterface *vm_port = static_cast(intf); + vm_sub_type_ = vm_port->sub_type(); if (dhcp_enable_ != vm_port->dhcp_enable_config()) { dhcp_enable_ = vm_port->dhcp_enable_config(); ret = true; @@ -380,6 +384,10 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { encoder.set_h_op(op); switch (type_) { case Interface::VM_INTERFACE: { + if (vm_sub_type_ == VmInterface::TOR) + return 0; + if (l2_active_ == false) + return 0; if (dhcp_enable_) { flags |= VIF_FLAG_DHCP_ENABLED; } @@ -415,6 +423,7 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { case Interface::PHYSICAL: { encoder.set_vifr_type(VIF_TYPE_PHYSICAL); flags |= VIF_FLAG_L3_ENABLED; + flags |= VIF_FLAG_L2_ENABLED; if (!persistent_) { flags |= VIF_FLAG_VHOST_PHYS; } @@ -444,6 +453,7 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { break; } flags |= VIF_FLAG_L3_ENABLED; + flags |= VIF_FLAG_L2_ENABLED; break; } diff --git a/src/vnsw/agent/ksync/interface_ksync.h b/src/vnsw/agent/ksync/interface_ksync.h index 6e58d2b8e34..c578c2a5295 100644 --- a/src/vnsw/agent/ksync/interface_ksync.h +++ b/src/vnsw/agent/ksync/interface_ksync.h @@ -88,6 +88,7 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { KSyncEntryPtr parent_; bool policy_enabled_; InetInterface::SubType sub_type_; + VmInterface::SubType vm_sub_type_; Interface::Type type_; uint16_t rx_vlan_id_; uint16_t tx_vlan_id_; diff --git a/src/vnsw/agent/ksync/nexthop_ksync.cc b/src/vnsw/agent/ksync/nexthop_ksync.cc index b09000a197e..38564623c80 100644 --- a/src/vnsw/agent/ksync/nexthop_ksync.cc +++ b/src/vnsw/agent/ksync/nexthop_ksync.cc @@ -702,12 +702,10 @@ int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { } case Composite::L3COMP: { flags |= NH_FLAG_MCAST; - flags |= NH_FLAG_COMPOSITE_L3; break; } case Composite::MULTIPROTO: { encoder.set_nhr_family(AF_UNSPEC); - flags |= NH_FLAG_COMPOSITE_MULTI_PROTO; break; } case Composite::ECMP: diff --git a/src/vnsw/agent/ksync/route_ksync.cc b/src/vnsw/agent/ksync/route_ksync.cc index 993953df820..441833f6dce 100644 --- a/src/vnsw/agent/ksync/route_ksync.cc +++ b/src/vnsw/agent/ksync/route_ksync.cc @@ -14,6 +14,7 @@ #include #include +#include "cmn/agent.h" #include "oper/interface_common.h" #include "oper/nexthop.h" #include "oper/route_common.h" @@ -45,14 +46,14 @@ RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) : vrf_id_(rt->vrf_id()), nh_(NULL), label_(0), proxy_arp_(false), tunnel_type_(TunnelType::DefaultType()), wait_for_traffic_(false) { boost::system::error_code ec; - switch (rt->GetTableType()) { + rt_type_ = rt->GetTableType(); + switch (rt_type_) { case Agent::INET4_UNICAST: { const InetUnicastRouteEntry *uc_rt = static_cast(rt); addr_ = uc_rt->addr(); src_addr_ = IpAddress::from_string("0.0.0.0", ec).to_v4(); prefix_len_ = uc_rt->plen(); - rt_type_ = RT_UCAST; break; } case Agent::INET6_UNICAST: { @@ -61,7 +62,6 @@ RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) : addr_ = uc_rt->addr(); src_addr_ = Ip6Address(); prefix_len_ = uc_rt->plen(); - rt_type_ = RT_UCAST; break; } case Agent::INET4_MULTICAST: { @@ -70,14 +70,12 @@ RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) : addr_ = mc_rt->dest_ip_addr(); src_addr_ = mc_rt->src_ip_addr(); prefix_len_ = 32; - rt_type_ = RT_MCAST; break; } case Agent::LAYER2: { const Layer2RouteEntry *l2_rt = static_cast(rt); mac_ = l2_rt->GetAddress(); - rt_type_ = RT_LAYER2; prefix_len_ = 0; break; } @@ -140,11 +138,12 @@ bool RouteKSyncEntry::IsLess(const KSyncEntry &rhs) const { return rt_type_ < entry.rt_type_; //First unicast - if (rt_type_ == RT_UCAST) { + if ((rt_type_ == Agent::INET4_UNICAST) || + (rt_type_ == Agent::INET6_UNICAST)) { return UcIsLess(rhs); } - if (rt_type_ == RT_LAYER2) { + if (rt_type_ == Agent::LAYER2) { return L2IsLess(rhs); } @@ -200,7 +199,7 @@ bool RouteKSyncEntry::Sync(DBEntry *e) { } //Bother for label for unicast and EVPN routes - if (rt_type_ == RT_UCAST || rt_type_ == RT_LAYER2) { + if (rt_type_ != Agent::INET4_MULTICAST) { uint32_t old_label = label_; const AgentPath *path = (static_cast (e))->GetActivePath(); @@ -257,25 +256,24 @@ int RouteKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen, encoder.set_h_op(op); encoder.set_rtr_rid(0); - encoder.set_rtr_rt_type(rt_type_); encoder.set_rtr_vrf_id(vrf_id_); - if (rt_type_ != RT_LAYER2) { + if (rt_type_ != Agent::LAYER2) { if (addr_.is_v4()) { encoder.set_rtr_family(AF_INET); boost::array bytes = addr_.to_v4().to_bytes(); std::vector rtr_prefix(bytes.begin(), bytes.end()); encoder.set_rtr_prefix(rtr_prefix); - boost::array src_bytes = src_addr_.to_v4().to_bytes(); - std::vector rtr_src(src_bytes.begin(), src_bytes.end()); - encoder.set_rtr_src(rtr_src); + //boost::array src_bytes = src_addr_.to_v4().to_bytes(); + //std::vector rtr_src(src_bytes.begin(), src_bytes.end()); + //encoder.set_rtr_src(rtr_src); } else if (addr_.is_v6()) { encoder.set_rtr_family(AF_INET6); boost::array bytes = addr_.to_v6().to_bytes(); std::vector rtr_prefix(bytes.begin(), bytes.end()); encoder.set_rtr_prefix(rtr_prefix); - boost::array src_bytes = src_addr_.to_v6().to_bytes(); - std::vector rtr_src(src_bytes.begin(), src_bytes.end()); - encoder.set_rtr_src(rtr_src); + //boost::array src_bytes = src_addr_.to_v6().to_bytes(); + //std::vector rtr_src(src_bytes.begin(), src_bytes.end()); + //encoder.set_rtr_src(rtr_src); } encoder.set_rtr_prefix_len(prefix_len_); } else { @@ -288,14 +286,14 @@ int RouteKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen, int label = 0; int flags = 0; - if (rt_type_ == RT_UCAST || rt_type_ == RT_LAYER2) { + if (rt_type_ != Agent::INET4_MULTICAST) { if (nexthop != NULL && nexthop->type() == NextHop::TUNNEL) { label = label_; flags |= VR_RT_LABEL_VALID_FLAG; } } - if (rt_type_ == RT_LAYER2) { + if (rt_type_ == Agent::LAYER2) { flags |= 0x02; label = label_; if (nexthop != NULL && nexthop->type() == NextHop::COMPOSITE) { @@ -350,7 +348,8 @@ int RouteKSyncEntry::DeleteMsg(char *buf, int buf_len) { NHKSyncEntry *ksync_nh = NULL; // IF multicast or EVPN delete unconditionally - if (rt_type_ == RT_MCAST || rt_type_ == RT_LAYER2) { + if ((rt_type_ == Agent::LAYER2) || + (rt_type_ == Agent::INET4_MULTICAST)) { return DeleteInternal(nh(), 0, 0, false, buf, buf_len); } diff --git a/src/vnsw/agent/ksync/route_ksync.h b/src/vnsw/agent/ksync/route_ksync.h index 535bf68bd7d..0ffcdcbba1d 100644 --- a/src/vnsw/agent/ksync/route_ksync.h +++ b/src/vnsw/agent/ksync/route_ksync.h @@ -20,8 +20,6 @@ #include "ksync/agent_ksync_types.h" #include "ksync/nexthop_ksync.h" -#define RT_LAYER2 2 - class RouteKSyncObject; class RouteKSyncEntry : public KSyncNetlinkDBEntry { @@ -58,7 +56,7 @@ class RouteKSyncEntry : public KSyncNetlinkDBEntry { bool McIsLess(const KSyncEntry &rhs) const; bool L2IsLess(const KSyncEntry &rhs) const; RouteKSyncObject* ksync_obj_; - uint32_t rt_type_; + Agent::RouteTableType rt_type_; uint32_t vrf_id_; IpAddress addr_; IpAddress src_addr_; diff --git a/src/vnsw/agent/oper/agent.sandesh b/src/vnsw/agent/oper/agent.sandesh index 29a5639cbac..ee6f76e0419 100644 --- a/src/vnsw/agent/oper/agent.sandesh +++ b/src/vnsw/agent/oper/agent.sandesh @@ -77,6 +77,7 @@ struct VnIpamData { 3: string gateway; 4: string ipam_name; 5: string dhcp_enable; + 6: string dns_server; } struct VnIpamHostRoutes { @@ -811,6 +812,8 @@ struct VnObjectLogIpam { 2: i32 prefix_len; 3: optional string gateway_ip; 4: string ipam_name; + 5: string dhcp_enable; + 6: string dns_server; } struct VnObjectLogInfo { diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index aad8f2464ea..b16a505c8d8 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -527,6 +527,7 @@ AgentPath *AgentRoute::FindLocalVmPortPath() const { if (path->peer()->GetType() == Peer::ECMP_PEER || path->peer()->GetType() == Peer::VGW_PEER || path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER || + path->peer()->GetType() == Peer::MULTICAST_TOR_PEER || path->peer()->GetType() == Peer::OVS_PEER) { return const_cast(path); } @@ -700,3 +701,179 @@ void AgentRouteTable::StalePathFromPeer(DBTablePartBase *part, AgentRoute *rt, part->Notify(rt); } } + +bool AgentRoute::ReComputeMulticastPaths(AgentPath *path, bool del) { + if (path->peer() == NULL) { + return false; + } + + Agent *agent = + (static_cast (get_table()))->agent(); + std::vector delete_paths; + if (del && (path->peer() == agent->multicast_peer())) + return false; + + //Possible paths: + //EVPN path - can be from multiple peers. + //Fabric path - from multicast builder + //Multicast peer + AgentPath *multicast_peer_path = NULL; + AgentPath *local_peer_path = NULL; + AgentPath *evpn_peer_path = NULL; + AgentPath *fabric_peer_path = NULL; + AgentPath *tor_peer_path = NULL; + + //Delete path label + if (del) { + MplsLabel::DeleteReq(path->label()); + } + + for (Route::PathList::iterator it = GetPathList().begin(); + it != GetPathList().end(); it++) { + AgentPath *it_path = + static_cast(it.operator->()); + //Handle deletions + if (del && (path->peer() == it_path->peer())) { + continue; + } + + //Handle Add/Changes + if (it_path->peer() == agent->local_vm_peer()) { + local_peer_path = it_path; + } else if (it_path->peer()->GetType() == Peer::MULTICAST_TOR_PEER) { + tor_peer_path = it_path; + } else if (it_path->peer()->GetType() == Peer::BGP_PEER) { + //Pick up the first peer. + if (evpn_peer_path == NULL) + evpn_peer_path = it_path; + } else if (it_path->peer()->GetType() == + Peer::MULTICAST_FABRIC_TREE_BUILDER) { + fabric_peer_path = it_path; + } else if (it_path->peer() == agent->multicast_peer()) { + multicast_peer_path = it_path; + } + } + + //all paths are gone so delete multicast_peer path as well + if ((local_peer_path == NULL) && + (tor_peer_path == NULL) && + (evpn_peer_path == NULL) && + (fabric_peer_path == NULL) && + (multicast_peer_path != NULL)) { + RemovePath(multicast_peer_path); + return true; + } + + uint32_t old_fabric_mpls_label = 0; + if (multicast_peer_path == NULL) { + multicast_peer_path = new AgentPath(agent->multicast_peer(), NULL); + InsertPath(multicast_peer_path); + } else { + old_fabric_mpls_label = multicast_peer_path->label(); + } + + ComponentNHKeyList component_nh_list; + + if (tor_peer_path) { + NextHopKey *tor_peer_key = + static_cast((tor_peer_path-> + nexthop(agent)->GetDBRequestKey()).release()); + std::auto_ptr key4(tor_peer_key); + ComponentNHKeyPtr component_nh_data4(new ComponentNHKey(0, key4)); + component_nh_list.push_back(component_nh_data4); + } + + if (evpn_peer_path) { + NextHopKey *evpn_peer_key = + static_cast((evpn_peer_path-> + nexthop(agent)->GetDBRequestKey()).release()); + std::auto_ptr key2(evpn_peer_key); + ComponentNHKeyPtr component_nh_data2(new ComponentNHKey(0, key2)); + component_nh_list.push_back(component_nh_data2); + } + + if (fabric_peer_path) { + NextHopKey *fabric_peer_key = + static_cast((fabric_peer_path-> + nexthop(agent)->GetDBRequestKey()).release()); + std::auto_ptr key3(fabric_peer_key); + ComponentNHKeyPtr component_nh_data3(new ComponentNHKey(0, key3)); + component_nh_list.push_back(component_nh_data3); + } + + if (local_peer_path) { + NextHopKey *local_peer_key = + static_cast((local_peer_path-> + nexthop(agent)->GetDBRequestKey()).release()); + std::auto_ptr key1(local_peer_key); + ComponentNHKeyPtr component_nh_data1(new ComponentNHKey(0, key1)); + component_nh_list.push_back(component_nh_data1); + } + + DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); + nh_req.key.reset(new CompositeNHKey(Composite::L2COMP, + false, + component_nh_list, + vrf()->GetName())); + nh_req.data.reset(new CompositeNHData()); + agent->nexthop_table()->Process(nh_req); + NextHop *nh = static_cast(agent->nexthop_table()-> + FindActiveEntry(nh_req.key.get())); + //NH may not get added if VRF is marked for delete. Route may be in + //transition of getting deleted, skip NH modification. + if (!nh) { + return false; + } + + bool ret = false; + if (tor_peer_path) { + ret = MulticastRoute::CopyPathParameters(agent, + multicast_peer_path, + (tor_peer_path ? tor_peer_path-> + dest_vn_name() : ""), + (tor_peer_path ? tor_peer_path-> + unresolved() : false), + (tor_peer_path ? tor_peer_path-> + vxlan_id() : 0), + (fabric_peer_path ? fabric_peer_path-> + label() : 0), + TunnelType::VxlanType(), + false, + nh); + } + if (local_peer_path) { + ret = MulticastRoute::CopyPathParameters(agent, + multicast_peer_path, + (local_peer_path ? local_peer_path-> + dest_vn_name() : ""), + (local_peer_path ? local_peer_path-> + unresolved() : false), + (local_peer_path ? local_peer_path-> + vxlan_id() : 0), + (fabric_peer_path ? fabric_peer_path-> + label() : 0), + TunnelType::AllType(), + false, + nh); + } + + //Bake all MPLS label + if (fabric_peer_path) { + //Add new label + MplsLabel::CreateMcastLabelReq(fabric_peer_path->label(), + Composite::L2COMP, + component_nh_list, + vrf()->GetName()); + //Delete Old label, in case label has changed for same peer. + if (old_fabric_mpls_label != fabric_peer_path->label()) { + MplsLabel::DeleteReq(old_fabric_mpls_label); + } + } + if (evpn_peer_path) { + MplsLabel::CreateMcastLabelReq(evpn_peer_path->label(), + Composite::L2COMP, + component_nh_list, + vrf()->GetName()); + } + return ret; +} diff --git a/src/vnsw/agent/oper/agent_route.h b/src/vnsw/agent/oper/agent_route.h index 529059237fe..06e0d5a6d32 100644 --- a/src/vnsw/agent/oper/agent_route.h +++ b/src/vnsw/agent/oper/agent_route.h @@ -249,6 +249,7 @@ class AgentRoute : public Route { void FillTrace(RouteInfo &route, Trace event, const AgentPath *path); bool WaitForTraffic() const; protected: + bool ReComputeMulticastPaths(AgentPath *path, bool del); void SetVrf(VrfEntryRef vrf) { vrf_ = vrf; } void RemovePathInternal(AgentPath *path); void RemovePath(AgentPath *path); diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 84589ba2c68..cadeb67a835 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -405,12 +405,26 @@ bool InetUnicastRouteEntry::EcmpDeletePath(AgentPath *path) { } bool InetUnicastRouteEntry::ReComputePathAdd(AgentPath *path) { + Agent *agent = + (static_cast (get_table()))->agent(); + AgentPath *local_path = FindPath(agent->local_peer()); + if (local_path && local_path->is_subnet_discard()) { + return ReComputeMulticastPaths(path, false); + } + // ECMP path are managed by route module. Update ECMP path with // addition of new path return EcmpAddPath(path); } bool InetUnicastRouteEntry::ReComputePathDeletion(AgentPath *path) { + Agent *agent = + (static_cast (get_table()))->agent(); + AgentPath *local_path = FindPath(agent->local_peer()); + if (local_path && local_path->is_subnet_discard()) { + return ReComputeMulticastPaths(path, true); + } + // ECMP path are managed by route module. Update ECMP path with // deletion of new path return EcmpDeletePath(path); diff --git a/src/vnsw/agent/oper/layer2_route.cc b/src/vnsw/agent/oper/layer2_route.cc index 64c4bbf9af2..b6b5dd6473e 100644 --- a/src/vnsw/agent/oper/layer2_route.cc +++ b/src/vnsw/agent/oper/layer2_route.cc @@ -175,6 +175,22 @@ void Layer2AgentRouteTable::AddLayer2BroadcastRoute(const Peer *peer, Layer2TableEnqueue(Agent::GetInstance(), &req); } +void Layer2AgentRouteTable::AddLayer2ReceiveRoute(const Peer *peer, + const string &vrf_name, + const string &vn_name, + const MacAddress &mac, + const string &interface, + bool policy) { + Agent *agent = Agent::GetInstance(); + DBRequest req; + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + req.key.reset(new Layer2RouteKey(peer, vrf_name, mac, 0)); + + PacketInterfaceKey intf_key(nil_uuid(), agent->pkt_interface_name()); + req.data.reset(new HostRoute(intf_key, vn_name)); + + Layer2TableEnqueue(agent, &req); +} void Layer2AgentRouteTable::AddRemoteVmRouteReq(const Peer *peer, const string &vrf_name, @@ -292,151 +308,6 @@ uint32_t Layer2RouteEntry::GetActiveLabel() const { return label; } -bool Layer2RouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) { - if (path->peer() == NULL) { - return false; - } - - Agent *agent = - (static_cast (get_table()))->agent(); - std::vector delete_paths; - if (del && (path->peer() == agent->multicast_peer())) - return false; - - //Possible paths: - //EVPN path - can be from multiple peers. - //Fabric path - from multicast builder - //Multicast peer - AgentPath *multicast_peer_path = NULL; - AgentPath *local_peer_path = NULL; - AgentPath *evpn_peer_path = NULL; - AgentPath *fabric_peer_path = NULL; - - //Delete path label - if (del) { - MplsLabel::DeleteReq(path->label()); - } - - for (Route::PathList::iterator it = GetPathList().begin(); - it != GetPathList().end(); it++) { - AgentPath *it_path = - static_cast(it.operator->()); - //Handle deletions - if (del && (path->peer() == it_path->peer())) { - continue; - } - - //Handle Add/Changes - if (it_path->peer() == agent->local_vm_peer()) { - local_peer_path = it_path; - } else if (it_path->peer()->GetType() == Peer::BGP_PEER) { - //Pick up the first peer. - if (evpn_peer_path == NULL) - evpn_peer_path = it_path; - } else if (it_path->peer()->GetType() == - Peer::MULTICAST_FABRIC_TREE_BUILDER) { - fabric_peer_path = it_path; - } else if (it_path->peer() == agent->multicast_peer()) { - multicast_peer_path = it_path; - } - } - - //all paths are gone so delete multicast_peer path as well - if ((local_peer_path == NULL) && - (evpn_peer_path == NULL) && - (fabric_peer_path == NULL) && - (multicast_peer_path != NULL)) { - RemovePath(multicast_peer_path); - return true; - } - - uint32_t old_fabric_mpls_label = 0; - if (multicast_peer_path == NULL) { - multicast_peer_path = new AgentPath(agent->multicast_peer(), NULL); - InsertPath(multicast_peer_path); - } else { - old_fabric_mpls_label = multicast_peer_path->label(); - } - - ComponentNHKeyList component_nh_list; - - if (evpn_peer_path) { - NextHopKey *evpn_peer_key = - static_cast((evpn_peer_path-> - nexthop(agent)->GetDBRequestKey()).release()); - std::auto_ptr key2(evpn_peer_key); - ComponentNHKeyPtr component_nh_data2(new ComponentNHKey(0, key2)); - component_nh_list.push_back(component_nh_data2); - } - - if (fabric_peer_path) { - NextHopKey *fabric_peer_key = - static_cast((fabric_peer_path-> - nexthop(agent)->GetDBRequestKey()).release()); - std::auto_ptr key3(fabric_peer_key); - ComponentNHKeyPtr component_nh_data3(new ComponentNHKey(0, key3)); - component_nh_list.push_back(component_nh_data3); - } - - if (local_peer_path) { - NextHopKey *local_peer_key = - static_cast((local_peer_path-> - nexthop(agent)->GetDBRequestKey()).release()); - std::auto_ptr key1(local_peer_key); - ComponentNHKeyPtr component_nh_data1(new ComponentNHKey(0, key1)); - component_nh_list.push_back(component_nh_data1); - } - - DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new CompositeNHKey(Composite::L2COMP, - false, - component_nh_list, - vrf()->GetName())); - nh_req.data.reset(new CompositeNHData()); - agent->nexthop_table()->Process(nh_req); - NextHop *nh = static_cast(agent->nexthop_table()-> - FindActiveEntry(nh_req.key.get())); - //NH may not get added if VRF is marked for delete. Route may be in - //transition of getting deleted, skip NH modification. - if (!nh) { - return false; - } - - bool ret = MulticastRoute::CopyPathParameters(agent, - multicast_peer_path, - (local_peer_path ? local_peer_path-> - dest_vn_name() : ""), - (local_peer_path ? local_peer_path-> - unresolved() : false), - (local_peer_path ? local_peer_path-> - vxlan_id() : 0), - (fabric_peer_path ? fabric_peer_path-> - label() : 0), - TunnelType::AllType(), - false, - nh); - - //Bake all MPLS label - if (fabric_peer_path) { - //Add new label - MplsLabel::CreateMcastLabelReq(fabric_peer_path->label(), - Composite::L2COMP, - component_nh_list, - vrf()->GetName()); - //Delete Old label, in case label has changed for same peer. - if (old_fabric_mpls_label != fabric_peer_path->label()) { - MplsLabel::DeleteReq(old_fabric_mpls_label); - } - } - if (evpn_peer_path) { - MplsLabel::CreateMcastLabelReq(evpn_peer_path->label(), - Composite::L2COMP, - component_nh_list, - vrf()->GetName()); - } - return ret; -} - string Layer2RouteEntry::ToString() const { return mac_.ToString(); } diff --git a/src/vnsw/agent/oper/layer2_route.h b/src/vnsw/agent/oper/layer2_route.h index 52e6bca8910..274e6a5f230 100644 --- a/src/vnsw/agent/oper/layer2_route.h +++ b/src/vnsw/agent/oper/layer2_route.h @@ -64,6 +64,12 @@ class Layer2AgentRouteTable : public AgentRouteTable { Composite::Type type, ComponentNHKeyList &component_nh_key_list); + static void AddLayer2ReceiveRoute(const Peer *peer, + const string &vrf_name, + const string &vn_name, + const MacAddress &mac, + const string &interface, + bool policy); static void DeleteReq(const Peer *peer, const string &vrf_name, const MacAddress &mac, uint32_t ethernet_tag, @@ -124,8 +130,6 @@ class Layer2RouteEntry : public AgentRoute { const uint32_t GetVmIpPlen() const {return plen_;} private: - bool ReComputeMulticastPaths(AgentPath *path, bool del); - MacAddress mac_; Ip4Address vm_ip_; uint32_t plen_; diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index db770bace66..172fe18b220 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -24,6 +26,11 @@ #include using namespace std; +using AGENT::PhysicalDeviceVnTable; +using AGENT::PhysicalDeviceTable; +using AGENT::PhysicalDeviceVnEntry; +using AGENT::PhysicalDeviceEntry; + #define INVALID_PEER_IDENTIFIER ControllerPeerPath::kInvalidPeerIdentifier MulticastHandler *MulticastHandler::obj_; @@ -40,6 +47,12 @@ void MulticastHandler::Register() { boost::bind(&MulticastHandler::ModifyVN, _1, _2)); interface_listener_id_ = agent_->interface_table()->Register( boost::bind(&MulticastHandler::ModifyVmInterface, _1, _2)); + if (Agent::GetInstance()->tsn_enabled()) { + physical_device_vn_listener_id_ = + agent_->device_manager()->physical_device_vn_table()-> + Register(boost::bind(&MulticastHandler::ModifyTor, + _1, _2)); + } MulticastHandler::GetInstance()->GetMulticastObjList().clear(); } @@ -62,6 +75,8 @@ void MulticastHandler::AddL2BroadcastRoute(MulticastGroupObject *obj, //Add Layer2 FF:FF:FF:FF:FF:FF ComponentNHKeyList component_nh_key_list = GetInterfaceComponentNHKeyList(obj, InterfaceNHFlags::LAYER2); + if (component_nh_key_list.size() == 0) + return; Layer2AgentRouteTable::AddLayer2BroadcastRoute(agent_->local_vm_peer(), vrf_name, vn_name, label, vxlan_id, @@ -139,6 +154,122 @@ void MulticastHandler::ModifyVN(DBTablePartBase *partition, DBEntryBase *e) MulticastHandler::GetInstance()->HandleIpam(vn); MulticastHandler::GetInstance()->HandleFamilyConfig(vn); MulticastHandler::GetInstance()->HandleVxLanChange(vn); + MulticastHandler::GetInstance()->HandleTor(vn); +} + +void HandleTorRoute(const PhysicalDeviceVnEntry *device_vn, + const VnEntry *vn) +{ + if (device_vn->vn() != vn) + return; + + PhysicalDeviceEntry *physical_device = device_vn->device(); + + uint32_t vxlan_id = vn->GetVxLanId(); + boost::system::error_code ec; + Ip4Address addr = physical_device->ip().to_v4(); + addr = IpAddress::from_string("34.34.34.34", ec).to_v4(); + MulticastGroupObject *obj = MulticastHandler::GetInstance()-> + FindFloodGroupObject(vn->GetVrf()->GetName()); + bool add_request = true; + + if (device_vn->IsDeleted()) { + if (obj == NULL) + return; + obj->DeleteFromTorList(addr, vxlan_id, TunnelType::VxlanType()); + if (obj->tor_olist().empty()) + add_request = false; + } + + if (!add_request) { + Layer2AgentRouteTable::DeleteBroadcastReq(Agent::GetInstance()-> + multicast_tor_peer(), + vn->GetVrf()->GetName(), + vxlan_id); + MulticastHandler::GetInstance()-> + DeleteMulticastObject(vn->GetVrf()->GetName(), addr); + return; + } + + if (add_request) { + //TBD Make a common func to create object + if (obj == NULL) { + boost::system::error_code ec; + Ip4Address broadcast = IpAddress::from_string("255.255.255.255", + ec).to_v4(); + obj = MulticastHandler::GetInstance()-> + CreateMulticastGroupObject(vn->GetVrf()->GetName(), + broadcast, + vn->GetName()); + } + + obj->AddInTorList(addr, vxlan_id, TunnelType::VxlanType()); + } + + MulticastHandler::ModifyTorMembers(Agent::GetInstance()-> + multicast_tor_peer(), + vn->GetVrf()->GetName(), + obj->tor_olist(), + vn->GetVxLanId(), + 1); +} + +void MulticastHandler::ModifyTor(DBTablePartBase *partition, DBEntryBase *e) +{ + const PhysicalDeviceVnEntry *device_vn = + static_cast(e); + + //Take IP out of it + //PhysicalDeviceEntry *device = device_vn->device(); + VnEntry *vn = device_vn->vn(); + PhysicalDeviceEntry *physical_device = device_vn->device(); + + if (!physical_device || !vn || !(vn->GetVrf())) + return; + + if (vn->GetVrf() == NULL) { + return; + } + HandleTorRoute(device_vn, vn); +} + +void MulticastHandler::WalkDone() { +} + +bool MulticastHandler::TorWalker(DBTablePartBase *partition, + DBEntryBase *entry, + const VnEntry *vn) { + PhysicalDeviceVnEntry *physical_vn_device = + static_cast(entry); + HandleTorRoute(physical_vn_device, vn); + return true; +} + +void MulticastHandler::HandleTor(const VnEntry *vn) +{ + if (!vn->GetVrf()) + return; + if ((Agent::GetInstance()->device_manager() == NULL) || + (Agent::GetInstance()->device_manager()->physical_device_vn_table() + == NULL)) { + return; + } + + //Start a walk on VN table + DBTableWalker *walker = Agent::GetInstance()->db()->GetWalker(); + walker->WalkTable(Agent::GetInstance()->device_manager()-> + physical_device_vn_table(), NULL, + boost::bind(&MulticastHandler::TorWalker, this, _1, + _2, vn), + boost::bind(&MulticastHandler::WalkDone, this)); +} + +MulticastGroupObject *MulticastHandler::CreateMulticastGroupObject +(const string &vrf_name, const Ip4Address &ip_addr, const string &vn_name) { + MulticastGroupObject *obj = + new MulticastGroupObject(vrf_name, ip_addr, vn_name); + AddToMulticastObjList(obj); + return obj; } void MulticastHandler::HandleIpam(const VnEntry *vn) { @@ -186,12 +317,16 @@ void MulticastHandler::ModifyVmInterface(DBTablePartBase *partition, return; } + vm_itf = static_cast(intf); + if (vm_itf->sub_type() == VmInterface::TOR) { + //Ignore TOR VMI, they are not active VMI. + return; + } + if (intf->IsDeleted() || (intf->l2_active() == false)) { MulticastHandler::GetInstance()->DeleteVmInterface(intf); return; } - - vm_itf = static_cast(intf); assert(vm_itf->vn() != NULL); MulticastHandler::GetInstance()->AddVmInterfaceInFloodGroup(vm_itf); @@ -244,13 +379,17 @@ void MulticastHandler::DeleteVmInterface(const Interface *intf) //Delete multicast object for vrf/G void MulticastHandler::DeleteMulticastObject(const std::string &vrf_name, const Ip4Address &grp_addr) { - MCTRACE(Log, "delete obj vrf/grp/size ", vrf_name, grp_addr.to_string(), - this->GetMulticastObjList().size()); for(std::set::iterator it = this->GetMulticastObjList().begin(); it != this->GetMulticastObjList().end(); it++) { if (((*it)->vrf_name() == vrf_name) && ((*it)->GetGroupAddress() == grp_addr)) { + if (((*it)->GetLocalListSize() != 0) || + !(((*it)->tor_olist()).empty())) + return; + MCTRACE(Log, "delete obj vrf/grp/size ", vrf_name, + grp_addr.to_string(), + this->GetMulticastObjList().size()); delete (*it); this->GetMulticastObjList().erase(it++); break; @@ -375,7 +514,8 @@ void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj, ComponentNHKeyList component_nh_key_list; //dummy list RebakeSubnetRoute(peer, vrf_name, 0, ethernet_tag, obj ? obj->GetVnName() : "", - true, component_nh_key_list); + true, component_nh_key_list, + comp_type); return; } @@ -434,10 +574,13 @@ void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj, TunnelType::AllType(), comp_type, component_nh_key_list); - if (comp_type == Composite::EVPN) { + //if ((comp_type == Composite::EVPN) || (comp_type == Composite::TOR)) { + MCTRACE(Log, "rebake subnet peer for subnet", vrf_name, + "255.255.255.255", 0); RebakeSubnetRoute(peer, obj->vrf_name(), label, obj->vxlan_id(), - obj->GetVnName(), false, component_nh_key_list); - } + obj->GetVnName(), false, component_nh_key_list, + comp_type); + //} } void MulticastHandler::RebakeSubnetRoute(const Peer *peer, @@ -446,10 +589,12 @@ void MulticastHandler::RebakeSubnetRoute(const Peer *peer, uint32_t vxlan_id, const std::string &vn_name, bool del_op, - const ComponentNHKeyList &comp_nh_list) + const ComponentNHKeyList &comp_nh_list, + COMPOSITETYPE comp_type) { //Expect only to handle EVPN information. - if (peer->GetType() != Peer::BGP_PEER) + if ((peer->GetType() != Peer::BGP_PEER) && + (peer->GetType() != Peer::MULTICAST_TOR_PEER)) return; std::vector &vrf_ipam = @@ -464,7 +609,7 @@ void MulticastHandler::RebakeSubnetRoute(const Peer *peer, if (del_op == false) { DBRequest nh_req; nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - nh_req.key.reset(new CompositeNHKey(Composite::EVPN, false, + nh_req.key.reset(new CompositeNHKey(comp_type, false, comp_nh_list, vrf_name)); nh_req.data.reset(new CompositeNHData()); //add route @@ -497,9 +642,8 @@ void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_itf) { //All broadcast addition 255.255.255.255 all_broadcast = this->FindGroupObject(vrf_name, broadcast); if (all_broadcast == NULL) { - all_broadcast = new MulticastGroupObject(vrf_name, broadcast, - vn_name); - AddToMulticastObjList(all_broadcast); + all_broadcast = CreateMulticastGroupObject(vrf_name, broadcast, + vn_name); add_route = true; } @@ -631,6 +775,41 @@ void MulticastHandler::ModifyTorMembers(const Peer *peer, MCTRACE(Log, "Add external TOR Olist ", vrf_name, grp.to_string(), 0); } +const OlistTunnelEntry *MulticastGroupObject::FindInTorList +(const Ip4Address &ip_addr, uint32_t vxlan_id, uint32_t tunnel_bmap) { + for (std::vector::iterator it = tor_olist_.begin(); + it != tor_olist_.end(); it++) { + if (((*it).daddr_ == ip_addr) && ((*it).label_ == vxlan_id) && + ((*it).tunnel_bmap_ == tunnel_bmap)) { + return &(*it); + } + } + return NULL; +} + +void MulticastGroupObject::AddInTorList(const Ip4Address &ip_addr, + uint32_t vxlan_id, + uint32_t tunnel_bmap) { + if (FindInTorList(ip_addr, vxlan_id, tunnel_bmap)) + return; + + tor_olist_.push_back(OlistTunnelEntry(vxlan_id, ip_addr, + tunnel_bmap)); +} + +void MulticastGroupObject::DeleteFromTorList(const Ip4Address &ip_addr, + uint32_t vxlan_id, + uint32_t tunnel_bmap) { + for (std::vector::iterator it = tor_olist_.begin(); + it != tor_olist_.end(); it++) { + if (((*it).daddr_ == ip_addr) && ((*it).label_ == vxlan_id) && + ((*it).tunnel_bmap_ == tunnel_bmap)) { + tor_olist_.erase(it); + return; + } + } +} + // Helper to delete fabric nh // For internal delete it uses invalid identifier. // For delete via control node it uses the sequence sent. diff --git a/src/vnsw/agent/oper/multicast.h b/src/vnsw/agent/oper/multicast.h index 236f53c6595..97f7c7bd90a 100644 --- a/src/vnsw/agent/oper/multicast.h +++ b/src/vnsw/agent/oper/multicast.h @@ -49,6 +49,7 @@ class MulticastGroupObject { boost::system::error_code ec; src_address_ = IpAddress::from_string("0.0.0.0", ec).to_v4(); local_olist_.clear(); + tor_olist_.clear(); }; MulticastGroupObject(const std::string &vrf_name, const Ip4Address &grp_addr, @@ -57,6 +58,7 @@ class MulticastGroupObject { evpn_mpls_label_(0), vxlan_id_(0), layer2_forwarding_(true), peer_identifier_(0), deleted_(false) { local_olist_.clear(); + tor_olist_.clear(); }; virtual ~MulticastGroupObject() { }; @@ -105,6 +107,14 @@ class MulticastGroupObject { int vxlan_id() const {return vxlan_id_;} void set_peer_identifier(uint64_t peer_id) {peer_identifier_ = peer_id;} uint64_t peer_identifier() {return peer_identifier_;} + void AddInTorList(const Ip4Address &ip_addr, uint32_t vxlan_id, + uint32_t tunnel_bmap); + void DeleteFromTorList(const Ip4Address &ip_addr, uint32_t vxlan_id, + uint32_t tunnel_bmap); + const OlistTunnelEntry *FindInTorList(const Ip4Address &ip_addr, + uint32_t vxlan_id, + uint32_t tunnel_bmap); + const TunnelOlist &tor_olist() const {return tor_olist_;} private: @@ -118,6 +128,7 @@ class MulticastGroupObject { uint64_t peer_identifier_; bool deleted_; std::list local_olist_; /* UUID of local i/f */ + TunnelOlist tor_olist_; friend class MulticastHandler; DISALLOW_COPY_AND_ASSIGN(MulticastGroupObject); @@ -130,6 +141,10 @@ class MulticastHandler { MulticastHandler(Agent *agent); virtual ~MulticastHandler() { } + MulticastGroupObject *CreateMulticastGroupObject(const string &vrf_name, + const Ip4Address &ip_addr, + const string &vn_name); + /* Called by XMPP to add ctrl node sent olist and label */ static void ModifyFabricMembers(const Peer *peer, const std::string &vrf_name, @@ -151,7 +166,13 @@ class MulticastHandler { const TunnelOlist &olist, uint32_t ethernet_tag, uint64_t peer_identifier = 0); - //Registered for VN notification + static void ModifyTor(DBTablePartBase *partition, DBEntryBase *e); + void HandleTor(const VnEntry *vn); + void WalkDone(); + bool TorWalker(DBTablePartBase *partition, DBEntryBase *entry, + const VnEntry *vn); + + //Registered for VN notification static void ModifyVN(DBTablePartBase *partition, DBEntryBase *e); //Registered for VM notification static void ModifyVmInterface(DBTablePartBase *partition, DBEntryBase *e); @@ -179,7 +200,8 @@ class MulticastHandler { uint32_t vxlan_id, const std::string &vn_name, bool del_op, - const ComponentNHKeyList &comp_nh_list); + const ComponentNHKeyList &comp_nh_list, + COMPOSITETYPE comp_type); void HandleIpam(const VnEntry *vn); void HandleFamilyConfig(const VnEntry *vn); void HandleVxLanChange(const VnEntry *vn); @@ -197,6 +219,8 @@ class MulticastHandler { void DeleteBroadcast(const Peer *peer, const std::string &vrf_name, uint32_t ethernet_tag); + void DeleteMulticastObject(const std::string &vrf_name, + const Ip4Address &grp_addr); const Agent *agent() const {return agent_;} void Terminate(); @@ -206,8 +230,6 @@ class MulticastHandler { void AddToMulticastObjList(MulticastGroupObject *obj) { multicast_obj_list_.insert(obj); }; - void DeleteMulticastObject(const std::string &vrf_name, - const Ip4Address &grp_addr); std::set &GetMulticastObjList() { return this->multicast_obj_list_; }; @@ -259,6 +281,7 @@ class MulticastHandler { DBTable::ListenerId vn_listener_id_; DBTable::ListenerId interface_listener_id_; + DBTable::ListenerId physical_device_vn_listener_id_;; DISALLOW_COPY_AND_ASSIGN(MulticastHandler); }; diff --git a/src/vnsw/agent/oper/peer.h b/src/vnsw/agent/oper/peer.h index 26fdc38906e..3f75a65b74c 100644 --- a/src/vnsw/agent/oper/peer.h +++ b/src/vnsw/agent/oper/peer.h @@ -19,6 +19,7 @@ #define ECMP_PEER_NAME "Ecmp" #define VGW_PEER_NAME "Vgw" #define MULTICAST_PEER_NAME "Multicast" +#define MULTICAST_TOR_PEER_NAME "Multicast TOR" #define MULTICAST_FABRIC_TREE_BUILDER_NAME "MulticastTreeBuilder" class AgentXmppChannel; @@ -41,7 +42,8 @@ class Peer { NOVA_PEER, VGW_PEER, MULTICAST_FABRIC_TREE_BUILDER, - OVS_PEER + OVS_PEER, + MULTICAST_TOR_PEER }; Peer(Type type, const std::string &name, bool controller_export); diff --git a/src/vnsw/agent/oper/vm.cc b/src/vnsw/agent/oper/vm.cc index 16164880e56..49630ae911a 100644 --- a/src/vnsw/agent/oper/vm.cc +++ b/src/vnsw/agent/oper/vm.cc @@ -121,7 +121,9 @@ bool VmTable::IFNodeToReq(IFMapNode *node, DBRequest &req){ autogen::IdPermsType id_perms = cfg->id_perms(); boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + string virtual_router_type = "none"; + VmInterface::VmSync(agent()->interface_table(), node); VmKey *key = new VmKey(u); VmData *data = NULL; if (node->IsDeleted()) { diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index b4293ae2d55..6b98d60d945 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -54,10 +54,12 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), - vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_() { + vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), + sub_type_(VmInterface::NONE) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; + configurer_ = (1 << VmInterface::CONFIG); } VmInterface::VmInterface(const boost::uuids::uuid &uuid, @@ -79,10 +81,11 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid, parent_(parent), oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), - vrf_assign_acl_(NULL) { + vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; + configurer_ = (1 << VmInterface::CONFIG); } VmInterface::~VmInterface() { @@ -483,6 +486,45 @@ static void ReadDhcpEnable(Agent *agent, VmInterfaceConfigData *data, } } +/* +VmInterface::SubType GetInterfaceSubTypeFromVm(IFMapNode *node) { + for (DBGraphVertex::adjacency_iterator iter = + node->begin(table->GetGraph()); + iter != node->end(table->GetGraph()); ++iter) { + + IFMapNode *adj_node = static_cast(iter.operator->()); + if (agent_->cfg_listener()->SkipNode(adj_node)) { + continue; + } + + if (adj_node->table()->display_name().compare("virtual-machine") == 0) { + return GetInterfaceSubTypeFromVm(adj_node); + } + + if (adj_node->table()->display_name().compare("virtual-router") == 0) { + return VmInterface::TOR; + } + } + return VmInterface::NOVA; +} +*/ + +//TBD Use link instead of device_owner +VmInterface::SubType GetInterfaceSubType(const std::string &device_owner) { + if (device_owner.compare("compute:nova") == 0) + return VmInterface::NOVA; + else + return VmInterface::TOR; +} + +void VmInterface::SetConfigurer(VmInterface::Configurer type) { + configurer_ |= (1 << type); +} + +void VmInterface::ResetConfigurer(VmInterface::Configurer type) { + configurer_ &= ~(1 << type); +} + // Virtual Machine Interface is added or deleted into oper DB from Nova // messages. The Config notify is used only to change interface. bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -495,31 +537,28 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); CfgIntTable *cfg_table = agent_->interface_config_table(); - CfgIntKey cfg_key(u); - CfgIntEntry *nova_entry = static_cast - (cfg_table->Find(&cfg_key)); - // If interface is not yet added to Config tree, return. - // This API is invoked again when the interface is added to config tree. - if (!nova_entry) { - return false; - } - - // Skip, if Nova has deleted the interface - if (nova_entry->IsDeleted()) { - return false; - } + VmInterface::SubType interface_sub_type = + GetInterfaceSubType(cfg->device_owner()); + std::string vn_name; + CfgIntKey cfg_key(u); + CfgIntEntry *cfg_entry = + static_cast (cfg_table->Find(&cfg_key)); // Skip config interface delete notification if (node->IsDeleted()) { - req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, u, "")); - req.data.reset(new VmInterfaceConfigData()); - return true; + VmInterface::Delete(this, u, VmInterface::CONFIG); + return false; } // Update interface configuration req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - InterfaceKey *key = new VmInterfaceKey(AgentKey::RESYNC, u, ""); + InterfaceKey *key = NULL; + if (interface_sub_type != VmInterface::NOVA) { + key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, u, + cfg->display_name()); + } else { + key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, u, ""); + } VmInterfaceConfigData *data; data = new VmInterfaceConfigData(); @@ -539,7 +578,7 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { ReadDhcpOptions(cfg, *data); //Fill config data items - data->cfg_name_= node->name(); + data->cfg_name_ = node->name(); data->admin_state_ = id_perms.enable; BuildVrfAssignRule(cfg, data); @@ -547,6 +586,7 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { SgUuidList sg_list(0); IFMapNode *vn_node = NULL; + // Walk Interface Graph to get VM, VN and FloatingIPList IFMapAgentTable *table = static_cast(node->table()); for (DBGraphVertex::adjacency_iterator iter = @@ -579,17 +619,18 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { VirtualNetwork *vn = static_cast (adj_node->GetObject()); assert(vn); + vn_name = vn->display_name(); autogen::IdPermsType id_perms = vn->id_perms(); CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, data->vn_uuid_); - if (nova_entry->GetVnUuid() != data->vn_uuid_) { + if (cfg_entry && (cfg_entry->GetVnUuid() != data->vn_uuid_)) { IFMAP_ERROR(InterfaceConfiguration, "Virtual-network UUID mismatch for interface:", UuidToString(u), "configuration VN uuid", UuidToString(data->vn_uuid_), "compute VN uuid", - UuidToString(nova_entry->GetVnUuid())); + UuidToString(cfg_entry->GetVnUuid())); } } @@ -597,17 +638,24 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { VirtualMachine *vm = static_cast (adj_node->GetObject()); assert(vm); + + //VM link to virtual-router tells kind of virtual-router. + //If virtual-router is not of type TOR/TSN, then NOVA is the only + //place from where interface gets created. So if subtype is unknown + //and there was a nova entry found then treat it as NOVA else + //ignore the request. Subsequent addition of VM or nova should + //re-invoke this routine. autogen::IdPermsType id_perms = vm->id_perms(); CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, data->vm_uuid_); - if (nova_entry->GetVmUuid() != data->vm_uuid_) { + if (cfg_entry && (cfg_entry->GetVmUuid() != data->vm_uuid_)) { IFMAP_ERROR(InterfaceConfiguration, "Virtual-machine UUID mismatch for interface:", UuidToString(u), "configuration VM UUID is", UuidToString(data->vm_uuid_), "compute VM uuid is", - UuidToString(nova_entry->GetVnUuid())); + UuidToString(cfg_entry->GetVnUuid())); } } @@ -626,8 +674,12 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { if (adj_node->table() == agent_->cfg()->cfg_route_table()) { BuildStaticRouteList(data, adj_node); } + } + data->sub_type_ = interface_sub_type; + data->vm_mac_ = cfg->mac_addresses().at(0); + // Get DHCP enable flag from subnet if (vn_node && data->addr_.to_ulong()) { ReadDhcpEnable(agent_, data, vn_node); @@ -691,28 +743,29 @@ Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table) const { Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table, const InterfaceData *data) const { - const VmInterfaceAddData *vm_data = - static_cast(data); + const VmInterfaceConfigData *vm_data = + static_cast(data); // Add is only supported with ADD_DEL_CHANGE key and data assert(vm_data->type_ == VmInterfaceData::ADD_DEL_CHANGE); - const VmInterfaceAddData *add_data = - static_cast(data); - Interface *parent = NULL; - if (add_data->tx_vlan_id_ != VmInterface::kInvalidVlanId && - add_data->rx_vlan_id_ != VmInterface::kInvalidVlanId && - add_data->parent_ != Agent::NullString()) { - PhysicalInterfaceKey key(add_data->parent_); + if (vm_data->tx_vlan_id_ != VmInterface::kInvalidVlanId && + vm_data->rx_vlan_id_ != VmInterface::kInvalidVlanId && + vm_data->parent_ != Agent::NullString()) { + PhysicalInterfaceKey key(vm_data->parent_); parent = static_cast (table->agent()->interface_table()->FindActiveEntry(&key)); assert(parent != NULL); } - return new VmInterface(uuid_, name_, add_data->ip_addr_, add_data->vm_mac_, - add_data->vm_name_, add_data->vm_project_uuid_, - add_data->tx_vlan_id_, add_data->rx_vlan_id_, - parent, add_data->ip6_addr_); + VmInterface *vmi = + new VmInterface(uuid_, name_, vm_data->addr_, vm_data->vm_mac_, + vm_data->vm_name_, vm_data->vm_uuid_, + vm_data->tx_vlan_id_, vm_data->rx_vlan_id_, + parent, vm_data->ip6_addr_); + vmi->SetConfigurer(vm_data->configurer_); + vmi->Resync(vm_data); + return vmi; } InterfaceKey *VmInterfaceKey::Clone() const { @@ -737,14 +790,19 @@ const Peer *VmInterface::peer() const { } bool VmInterface::OnChange(VmInterfaceData *data) { - return false; + if (data->type_ == VmInterfaceData::ADD_DEL_CHANGE) { + const VmInterfaceConfigData *cfg = static_cast + (data); + SetConfigurer(cfg->configurer_); + } + return Resync(data); } // Handle RESYNC DB Request. Handles multiple sub-types, // - CONFIG : RESYNC from config message // - IP_ADDR: RESYNC due to learning IP from DHCP // - MIRROR : RESYNC due to change in mirror config -bool VmInterface::Resync(VmInterfaceData *data) { +bool VmInterface::Resync(const VmInterfaceData *data) { bool ret = false; // Copy old values used to update config below @@ -762,22 +820,22 @@ bool VmInterface::Resync(VmInterfaceData *data) { bool local_pref_changed = false; if (data) { - if (data->type_ == VmInterfaceData::CONFIG) { - VmInterfaceConfigData *cfg = static_cast + if (data->type_ == VmInterfaceData::ADD_DEL_CHANGE) { + const VmInterfaceConfigData *cfg = static_cast (data); ret = CopyConfig(cfg, &sg_changed, &ecmp_changed, &local_pref_changed); } else if (data->type_ == VmInterfaceData::IP_ADDR) { - VmInterfaceIpAddressData *addr = - static_cast (data); + const VmInterfaceIpAddressData *addr = + static_cast (data); ret = ResyncIpAddress(addr); } else if (data->type_ == VmInterfaceData::MIRROR) { - VmInterfaceMirrorData *mirror = static_cast + const VmInterfaceMirrorData *mirror = static_cast (data); ret = ResyncMirror(mirror); } else if (data->type_ == VmInterfaceData::OS_OPER_STATE) { - VmInterfaceOsOperStateData *oper_state = - static_cast (data); + const VmInterfaceOsOperStateData *oper_state = + static_cast (data); ret = ResyncOsOperState(oper_state); } else { assert(0); @@ -855,28 +913,29 @@ bool VmInterface::CopyIpAddress(Ip4Address &addr) { // Copies configuration from DB-Request data. The actual applying of // configuration, like adding/deleting routes must be done with ApplyConfig() -bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, +bool VmInterface::CopyConfig(const VmInterfaceConfigData *data, bool *sg_changed, bool *ecmp_changed, bool *local_pref_changed) { bool ret = false; InterfaceTable *table = static_cast(get_table()); + if (table) { + VmEntry *vm = table->FindVmRef(data->vm_uuid_); + if (vm_.get() != vm) { + vm_ = vm; + ret = true; + } - VmEntry *vm = table->FindVmRef(data->vm_uuid_); - if (vm_.get() != vm) { - vm_ = vm; - ret = true; - } - - VrfEntry *vrf = table->FindVrfRef(data->vrf_name_); - if (vrf_.get() != vrf) { - vrf_ = vrf; - ret = true; - } + VrfEntry *vrf = table->FindVrfRef(data->vrf_name_); + if (vrf_.get() != vrf) { + vrf_ = vrf; + ret = true; + } - MirrorEntry *mirror = table->FindMirrorRef(data->analyzer_name_); - if (mirror_entry_.get() != mirror) { - mirror_entry_ = mirror; - ret = true; + MirrorEntry *mirror = table->FindMirrorRef(data->analyzer_name_); + if (mirror_entry_.get() != mirror) { + mirror_entry_ = mirror; + ret = true; + } } MirrorDirection mirror_direction = data->mirror_direction_; @@ -892,22 +951,24 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, } // Read ifindex for the interface - if (os_index_ == kInvalidIndex) { - GetOsParams(table->agent()); - if (os_index_ != kInvalidIndex) - ret = true; - } + if (table) { + if (os_index_ == kInvalidIndex) { + GetOsParams(table->agent()); + if (os_index_ != kInvalidIndex) + ret = true; + } - VnEntry *vn = table->FindVnRef(data->vn_uuid_); - if (vn_.get() != vn) { - vn_ = vn; - ret = true; - } + VnEntry *vn = table->FindVnRef(data->vn_uuid_); + if (vn_.get() != vn) { + vn_ = vn; + ret = true; + } - int vxlan_id = vn ? vn->GetVxLanId() : 0; - if (vxlan_id_ != vxlan_id) { - vxlan_id_ = vxlan_id; - ret = true; + int vxlan_id = vn ? vn->GetVxLanId() : 0; + if (vxlan_id_ != vxlan_id) { + vxlan_id_ = vxlan_id; + ret = true; + } } if (local_preference_ != data->local_preference_) { @@ -916,19 +977,7 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, ret = true; } - bool val = vn ? vn_->layer2_forwarding() : false; - if (layer2_forwarding_ != val) { - layer2_forwarding_ = val; - ret = true; - } - - val = vn ? vn_->layer3_forwarding() : false; - if (layer3_forwarding_ != val) { - layer3_forwarding_ = val; - ret = true; - } - - val = layer3_forwarding_ ? data->need_linklocal_ip_ : false; + bool val = layer3_forwarding_ ? data->need_linklocal_ip_ : false; if (need_linklocal_ip_ != val) { need_linklocal_ip_ = val; ret = true; @@ -975,7 +1024,7 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, // Audit operational and config floating-ip list FloatingIpSet &old_fip_list = floating_ip_list_.list_; - FloatingIpSet &new_fip_list = data->floating_ip_list_.list_; + const FloatingIpSet &new_fip_list = data->floating_ip_list_.list_; if (AuditList (floating_ip_list_, old_fip_list.begin(), old_fip_list.end(), new_fip_list.begin(), new_fip_list.end())) { @@ -986,7 +1035,7 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, // Audit operational and config Service VLAN list ServiceVlanSet &old_service_list = service_vlan_list_.list_; - ServiceVlanSet &new_service_list = data->service_vlan_list_.list_; + const ServiceVlanSet &new_service_list = data->service_vlan_list_.list_; if (AuditList (service_vlan_list_, old_service_list.begin(), old_service_list.end(), new_service_list.begin(), new_service_list.end())) { @@ -995,7 +1044,7 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, // Audit operational and config Static Route list StaticRouteSet &old_route_list = static_route_list_.list_; - StaticRouteSet &new_route_list = data->static_route_list_.list_; + const StaticRouteSet &new_route_list = data->static_route_list_.list_; if (AuditList (static_route_list_, old_route_list.begin(), old_route_list.end(), new_route_list.begin(), new_route_list.end())) { @@ -1004,7 +1053,8 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, // Audit operational and config allowed address pair AllowedAddressPairSet &old_aap_list = allowed_address_pair_list_.list_; - AllowedAddressPairSet &new_aap_list = data->allowed_address_pair_list_.list_; + const AllowedAddressPairSet &new_aap_list = data-> + allowed_address_pair_list_.list_; if (AuditList (allowed_address_pair_list_, old_aap_list.begin(), old_aap_list.end(), new_aap_list.begin(), new_aap_list.end())) { @@ -1013,7 +1063,7 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, // Audit operational and config Security Group list SecurityGroupEntrySet &old_sg_list = sg_list_.list_; - SecurityGroupEntrySet &new_sg_list = data->sg_list_.list_; + const SecurityGroupEntrySet &new_sg_list = data->sg_list_.list_; *sg_changed = AuditList (sg_list_, old_sg_list.begin(), old_sg_list.end(), @@ -1023,7 +1073,8 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, } VrfAssignRuleSet &old_vrf_assign_list = vrf_assign_rule_list_.list_; - VrfAssignRuleSet &new_vrf_assign_list = data->vrf_assign_rule_list_.list_; + const VrfAssignRuleSet &new_vrf_assign_list = data-> + vrf_assign_rule_list_.list_; if (AuditList (vrf_assign_rule_list_, old_vrf_assign_list.begin(), old_vrf_assign_list.end(), new_vrf_assign_list.begin(), @@ -1035,6 +1086,12 @@ bool VmInterface::CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, ecmp_ = data->ecmp_; *ecmp_changed = true; } + + if (sub_type_ != data->sub_type_) { + sub_type_= data->sub_type_; + ret = true; + } + return ret; } @@ -1118,6 +1175,11 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old bool sg_changed, bool old_ipv6_active, const Ip6Address &old_v6_addr, bool ecmp_mode_changed, bool local_pref_changed) { + //Need not apply config for TOR VMI as it is more of an inidicative + //interface. No route addition or NH addition happens for this interface. + if (sub_type_ == VmInterface::TOR) + return; + bool force_update = false; if (sg_changed || ecmp_mode_changed | local_pref_changed) { force_update = true; @@ -1182,7 +1244,7 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old } // Handle RESYNC message from mirror -bool VmInterface::ResyncMirror(VmInterfaceMirrorData *data) { +bool VmInterface::ResyncMirror(const VmInterfaceMirrorData *data) { bool ret = false; InterfaceTable *table = static_cast(get_table()); @@ -2859,6 +2921,34 @@ void VmInterface::VnSync(InterfaceTable *table, IFMapNode *node) { } } +//TBD replace it with ifmap dependancy manager +void VmInterface::VmSync(InterfaceTable *table, IFMapNode *node) { + CfgListener *cfg_listener = table->agent()->cfg_listener(); + if (cfg_listener->SkipNode(node)) { + return; + } + // Walk the node to get neighbouring interface + DBGraph *graph = + static_cast (node->table())->GetGraph(); + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + + IFMapNode *adj_node = static_cast(iter.operator->()); + if (cfg_listener->SkipNode(adj_node)) { + continue; + } + + if (adj_node->table() == + table->agent()->cfg()->cfg_vm_interface_table()) { + DBRequest req; + if (table->IFNodeToReq(adj_node, req) == true) { + LOG(DEBUG, "VM change sync for Port " << adj_node->name()); + table->Enqueue(&req); + } + } + } +} + const string VmInterface::GetAnalyzer() const { if (mirror_entry()) { return mirror_entry()->GetAnalyzerName(); @@ -2940,29 +3030,40 @@ void VmInterface::Add(InterfaceTable *table, const uuid &intf_uuid, const string &mac, const string &vm_name, const uuid &vm_project_uuid, uint16_t tx_vlan_id, uint16_t rx_vlan_id, const std::string &parent, - const Ip6Address &ip6) { + const Ip6Address &ip6, VmInterface::Configurer configurer) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, os_name)); - req.data.reset(new VmInterfaceAddData(addr, mac, vm_name, vm_project_uuid, - tx_vlan_id, rx_vlan_id, parent, ip6)); + req.data.reset(new VmInterfaceConfigData(addr, mac, vm_name, vm_project_uuid, + tx_vlan_id, rx_vlan_id, parent, ip6, + configurer)); table->Enqueue(&req); } // Delete a VM-Interface -void VmInterface::Delete(InterfaceTable *table, const uuid &intf_uuid) { +void VmInterface::Delete(InterfaceTable *table, const uuid &intf_uuid, + VmInterface::Configurer configurer) { + VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, ""); + VmInterface *vmi = static_cast(table-> + FindActiveEntry(&vmi_key)); + if (vmi) { + vmi->ResetConfigurer(configurer); + if (vmi->CanBeDeleted() == false) + return; + } + DBRequest req(DBRequest::DB_ENTRY_DELETE); req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, "")); req.data.reset(NULL); table->Enqueue(&req); } -bool VmInterface::CopyIp6Address(Ip6Address &addr) { +bool VmInterface::CopyIp6Address(const Ip6Address &addr) { bool ret = false; // Retain the old if new IP could not be got if (addr.is_unspecified()) { - addr = ip6_addr_; + return false; } if (ip6_addr_ != addr) { diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index f7853e73db1..f913c270b29 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -27,6 +27,17 @@ class VmInterface : public Interface { public: static const uint32_t kInvalidVlanId = 0xFFFF; + enum Configurer { + EXTERNAL, + CONFIG + }; + + enum SubType { + NONE, + TOR, + NOVA + }; + struct ListEntry { ListEntry() : installed_(false), del_pending_(false) { } ListEntry(bool installed, bool del_pending) : @@ -272,7 +283,7 @@ class VmInterface : public Interface { // DBEntry vectors KeyPtr GetDBRequestKey() const; std::string ToString() const; - bool Resync(VmInterfaceData *data); + bool Resync(const VmInterfaceData *data); bool OnChange(VmInterfaceData *data); // Accessor functions @@ -304,6 +315,10 @@ class VmInterface : public Interface { const Interface *parent() const { return parent_.get(); } bool ecmp() const { return ecmp_;} const OperDhcpOptions &oper_dhcp_options() const { return oper_dhcp_options_; } + uint8_t configurer() const {return configurer_;} + void SetConfigurer(VmInterface::Configurer type); + void ResetConfigurer(VmInterface::Configurer type); + bool CanBeDeleted() const {return (configurer_ == 0);} Interface::MirrorDirection mirror_direction() const { return mirror_direction_; @@ -365,6 +380,7 @@ class VmInterface : public Interface { void UpdateAllRoutes(); bool IsIpv6Active() const; + VmInterface::SubType sub_type() const {return sub_type_;} // Add a vm-interface static void Add(InterfaceTable *table, @@ -373,10 +389,12 @@ class VmInterface : public Interface { const std::string &mac, const std::string &vn_name, const boost::uuids::uuid &vm_project_uuid, uint16_t tx_vlan_id, uint16_t rx_vlan_id, - const std::string &parent, const Ip6Address &ipv6); + const std::string &parent, const Ip6Address &ipv6, + VmInterface::Configurer configurer); // Del a vm-interface static void Delete(InterfaceTable *table, - const boost::uuids::uuid &intf_uuid); + const boost::uuids::uuid &intf_uuid, + VmInterface::Configurer configurer); // Calback from configuration static void InstanceIpSync(InterfaceTable *table, IFMapNode *node); @@ -385,6 +403,7 @@ class VmInterface : public Interface { static void FloatingIpSync(InterfaceTable *table, IFMapNode *node); static void FloatingIpVrfSync(InterfaceTable *table, IFMapNode *node); static void VnSync(InterfaceTable *table, IFMapNode *node); + static void VmSync(InterfaceTable *table, IFMapNode *node); void AllocL2MplsLabel(bool force_update, bool policy_change); void DeleteL2MplsLabel(); @@ -420,13 +439,13 @@ class VmInterface : public Interface { bool OnResyncSecurityGroupList(VmInterfaceConfigData *data, bool new_ipv4_active); bool OnResyncStaticRoute(VmInterfaceConfigData *data, bool new_ipv4_active); - bool ResyncMirror(VmInterfaceMirrorData *data); + bool ResyncMirror(const VmInterfaceMirrorData *data); bool ResyncIpAddress(const VmInterfaceIpAddressData *data); bool ResyncOsOperState(const VmInterfaceOsOperStateData *data); bool ResyncConfig(VmInterfaceConfigData *data); bool CopyIpAddress(Ip4Address &addr); - bool CopyIp6Address(Ip6Address &addr); - bool CopyConfig(VmInterfaceConfigData *data, bool *sg_changed, + bool CopyIp6Address(const Ip6Address &addr); + bool CopyConfig(const VmInterfaceConfigData *data, bool *sg_changed, bool *ecmp_changed, bool *local_pref_changed); void ApplyConfig(bool old_ipv4_active,bool old_l2_active, bool old_policy, VrfEntry *old_vrf, const Ip4Address &old_addr, @@ -550,6 +569,8 @@ class VmInterface : public Interface { AclDBEntryRef vrf_assign_acl_; Ip4Address vm_ip_gw_addr_; Ip6Address vm_ip6_gw_addr_; + VmInterface::SubType sub_type_; + uint8_t configurer_; DISALLOW_COPY_AND_ASSIGN(VmInterface); }; @@ -587,7 +608,6 @@ struct VmInterfaceKey : public InterfaceKey { struct VmInterfaceData : public InterfaceData { enum Type { ADD_DEL_CHANGE, - CONFIG, MIRROR, IP_ADDR, OS_OPER_STATE @@ -601,31 +621,6 @@ struct VmInterfaceData : public InterfaceData { Type type_; }; -// Structure used when type=ADD_DEL_CHANGE. Used for creating of Vm-Interface -struct VmInterfaceAddData : public VmInterfaceData { - VmInterfaceAddData(const Ip4Address &ip_addr, - const std::string &vm_mac, - const std::string &vm_name, - const boost::uuids::uuid &vm_project_uuid, - const uint16_t tx_vlan_id, const uint16_t rx_vlan_id, - const std::string &parent, const Ip6Address &ip6_addr) : - VmInterfaceData(ADD_DEL_CHANGE), ip_addr_(ip_addr), ip6_addr_(ip6_addr), - vm_mac_(vm_mac), vm_name_(vm_name), vm_project_uuid_(vm_project_uuid), - tx_vlan_id_(tx_vlan_id), rx_vlan_id_(rx_vlan_id), parent_(parent) { - } - - virtual ~VmInterfaceAddData() { } - - Ip4Address ip_addr_; - Ip6Address ip6_addr_; - std::string vm_mac_; - std::string vm_name_; - boost::uuids::uuid vm_project_uuid_; - uint16_t tx_vlan_id_; - uint16_t rx_vlan_id_; - std::string parent_; -}; - // Structure used when type=IP_ADDR. Used to update IP-Address of VM-Interface struct VmInterfaceIpAddressData : public VmInterfaceData { VmInterfaceIpAddressData() : VmInterfaceData(IP_ADDR) { } @@ -651,20 +646,24 @@ struct VmInterfaceMirrorData : public VmInterfaceData { // Definition for structures when request queued from IFMap config. struct VmInterfaceConfigData : public VmInterfaceData { + VmInterfaceConfigData() : - VmInterfaceData(CONFIG), addr_(0), ip6_addr_(), vm_mac_(""), cfg_name_(""), + VmInterfaceData(ADD_DEL_CHANGE), addr_(0), ip6_addr_(), vm_mac_(""), cfg_name_(""), vm_uuid_(), vm_name_(), vn_uuid_(), vrf_name_(""), fabric_port_(true), need_linklocal_ip_(false), layer2_forwarding_(true), layer3_forwarding_(true), mirror_enable_(false), ecmp_(false), dhcp_enable_(true), analyzer_name_(""), oper_dhcp_options_(), mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), - allowed_address_pair_list_() { + allowed_address_pair_list_(), sub_type_(VmInterface::NONE), + configurer_(VmInterface::CONFIG), + tx_vlan_id_(VmInterface::kInvalidVlanId), + rx_vlan_id_(VmInterface::kInvalidVlanId), parent_("") { } VmInterfaceConfigData(const Ip4Address &addr, const std::string &mac, const std::string &vm_name) : - VmInterfaceData(CONFIG), addr_(addr), ip6_addr_(), vm_mac_(mac), + VmInterfaceData(ADD_DEL_CHANGE), addr_(addr), ip6_addr_(), vm_mac_(mac), cfg_name_(""), vm_uuid_(), vm_name_(vm_name), vn_uuid_(), vrf_name_(""), fabric_port_(true), need_linklocal_ip_(false), layer2_forwarding_(true), layer3_forwarding_(true), @@ -672,11 +671,34 @@ struct VmInterfaceConfigData : public VmInterfaceData { analyzer_name_(""), local_preference_(VmInterface::INVALID), oper_dhcp_options_(), mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), - allowed_address_pair_list_() { + allowed_address_pair_list_(), sub_type_(VmInterface::NONE), + configurer_(VmInterface::CONFIG), + tx_vlan_id_(VmInterface::kInvalidVlanId), + rx_vlan_id_(VmInterface::kInvalidVlanId), parent_("") { } - virtual ~VmInterfaceConfigData() { } + VmInterfaceConfigData(const Ip4Address &ip_addr, + const std::string &vm_mac, + const std::string &vm_name, + const boost::uuids::uuid &vm_project_uuid, + const uint16_t tx_vlan_id, const uint16_t rx_vlan_id, + const std::string &parent, + const Ip6Address &ip6_addr, + VmInterface::Configurer configurer) : + VmInterfaceData(ADD_DEL_CHANGE), addr_(ip_addr), ip6_addr_(ip6_addr), + vm_mac_(vm_mac), cfg_name_(""), vm_uuid_(vm_project_uuid), vm_name_(vm_name), + vn_uuid_(), vrf_name_(""), fabric_port_(true), need_linklocal_ip_(false), + layer2_forwarding_(true), layer3_forwarding_(true), + mirror_enable_(false), ecmp_(false), dhcp_enable_(true), + analyzer_name_(""), oper_dhcp_options_(), + mirror_direction_(Interface::UNKNOWN), sg_list_(), + floating_ip_list_(), service_vlan_list_(), static_route_list_(), + allowed_address_pair_list_(), sub_type_(VmInterface::NONE), + configurer_(configurer), tx_vlan_id_(tx_vlan_id), + rx_vlan_id_(rx_vlan_id), parent_("") { + } + virtual ~VmInterfaceConfigData() { } Ip4Address addr_; Ip6Address ip6_addr_; std::string vm_mac_; @@ -707,6 +729,11 @@ struct VmInterfaceConfigData : public VmInterfaceData { VmInterface::StaticRouteList static_route_list_; VmInterface::VrfAssignRuleList vrf_assign_rule_list_; VmInterface::AllowedAddressPairList allowed_address_pair_list_; + VmInterface::SubType sub_type_; + VmInterface::Configurer configurer_; + uint16_t tx_vlan_id_; + uint16_t rx_vlan_id_; + std::string parent_; }; #endif // vnsw_agent_vm_interface_hpp diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index 353b4e23aa8..3ab13a27d33 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -533,6 +533,7 @@ bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { VnIpam(subnets.ipam_subnets[i].subnet.ip_prefix, subnets.ipam_subnets[i].subnet.ip_prefix_len, subnets.ipam_subnets[i].default_gateway, + subnets.ipam_subnets[i].dns_server_address, subnets.ipam_subnets[i].enable_dhcp, ipam_name, subnets.ipam_subnets[i].dhcp_option_list.dhcp_option, subnets.ipam_subnets[i].host_routes.route)); @@ -643,15 +644,15 @@ void VnTable::IpamVnSync(IFMapNode *node) { return; } -void VnTable::UpdateSubnetGateway(const VnIpam &old_ipam, - const VnIpam &new_ipam, - VnEntry *vn) { +void VnTable::UpdateHostRoute(const IpAddress &old_address, + const IpAddress &new_address, + VnEntry *vn) { VrfEntry *vrf = vn->GetVrf(); if (vrf && (vrf->GetName() != Agent::GetInstance()-> linklocal_vrf_name())) { - AddHostRouteForGw(vn, new_ipam); - DelHostRouteForGw(vn, old_ipam); + AddHostRoute(vn, new_address); + DelHostRoute(vn, old_address); } } @@ -680,13 +681,26 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, // no change in entry bool gateway_changed = ((*it_old).default_gw != (*it_new).default_gw); + bool dns_changed = ((*it_old).dns_server != (*it_new).dns_server); if ((*it_old).installed) { (*it_new).installed = true; // VNIPAM comparator does not check for gateway. // If gateway is changed then take appropriate actions. + IpAddress unspecified; if (gateway_changed) { - UpdateSubnetGateway((*it_old), (*it_new), vn); + IpAddress &old_address = unspecified; + // remove old entry only if it is not used as dns server + if ((*it_old).default_gw != (*it_new).dns_server) + old_address = (*it_old).default_gw; + UpdateHostRoute(old_address, (*it_new).default_gw, vn); + } + if (dns_changed) { + IpAddress &old_address = unspecified; + // remove old entry only if it is not used as default gw + if ((*it_old).dns_server != (*it_new).default_gw) + old_address = (*it_old).dns_server; + UpdateHostRoute(old_address, (*it_new).dns_server, vn); } } else { AddIPAMRoutes(vn, *it_new); @@ -696,6 +710,9 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, if (gateway_changed) { (*it_old).default_gw = (*it_new).default_gw; } + if (dns_changed) { + (*it_old).dns_server = (*it_new).dns_server; + } // update DHCP options (*it_old).oper_dhcp_options = (*it_new).oper_dhcp_options; @@ -742,7 +759,9 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { if (vrf->GetName() == Agent::GetInstance()->linklocal_vrf_name()) { return; } - AddHostRouteForGw(vn, ipam); + AddHostRoute(vn, ipam.default_gw); + if (ipam.dns_server != ipam.default_gw) + AddHostRoute(vn, ipam.dns_server); AddSubnetRoute(vn, ipam); ipam.installed = true; } @@ -751,39 +770,41 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { void VnTable::DelIPAMRoutes(VnEntry *vn, VnIpam &ipam) { VrfEntry *vrf = vn->GetVrf(); if (vrf && ipam.installed) { - DelHostRouteForGw(vn, ipam); + DelHostRoute(vn, ipam.default_gw); + if (ipam.dns_server != ipam.default_gw) + DelHostRoute(vn, ipam.dns_server); DelSubnetRoute(vn, ipam); ipam.installed = false; } } // Add receive route for default gw -void VnTable::AddHostRouteForGw(VnEntry *vn, const VnIpam &ipam) { +void VnTable::AddHostRoute(VnEntry *vn, const IpAddress &address) { VrfEntry *vrf = vn->GetVrf(); - if (ipam.IsV4()) { + if (address.is_v4()) { static_cast(vrf-> GetInet4UnicastRouteTable())->AddHostRoute(vrf->GetName(), - ipam.default_gw.to_v4(), 32, vn->GetName()); - } else if (ipam.IsV6()) { + address.to_v4(), 32, vn->GetName()); + } else if (address.is_v6()) { static_cast(vrf-> GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(), - ipam.default_gw.to_v6(), 128, vn->GetName()); + address.to_v6(), 128, vn->GetName()); } } // Del receive route for default gw -void VnTable::DelHostRouteForGw(VnEntry *vn, const VnIpam &ipam) { +void VnTable::DelHostRoute(VnEntry *vn, const IpAddress &address) { VrfEntry *vrf = vn->GetVrf(); - if (ipam.IsV4()) { + if (address.is_v4()) { static_cast (vrf->GetInet4UnicastRouteTable())->DeleteReq (Agent::GetInstance()->local_peer(), vrf->GetName(), - ipam.default_gw.to_v4(), 32, NULL); - } else if (ipam.IsV6()) { + address.to_v4(), 32, NULL); + } else if (address.is_v6()) { static_cast (vrf->GetInet6UnicastRouteTable())->DeleteReq (Agent::GetInstance()->local_peer(), vrf->GetName(), - ipam.default_gw.to_v6(), 128, NULL); + address.to_v6(), 128, NULL); } } @@ -857,6 +878,7 @@ bool VnEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const { entry.set_gateway(vn_ipam[i].default_gw.to_string()); entry.set_ipam_name(vn_ipam[i].ipam_name); entry.set_dhcp_enable(vn_ipam[i].dhcp_enable ? "true" : "false"); + entry.set_dns_server(vn_ipam[i].dns_server.to_string()); vn_subnet_sandesh_list.push_back(entry); } data.set_ipam_data(vn_subnet_sandesh_list); @@ -944,6 +966,8 @@ void VnEntry::SendObjectLog(AgentLogEvent::type event) const { sandesh_ipam.set_prefix_len(ipam.plen); sandesh_ipam.set_gateway_ip(ipam.default_gw.to_string()); sandesh_ipam.set_ipam_name(ipam.ipam_name); + sandesh_ipam.set_dhcp_enable(ipam.dhcp_enable ? "true" : "false"); + sandesh_ipam.set_dns_server(ipam.dns_server.to_string()); ipam_list.push_back(sandesh_ipam); ++it; } diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index 3c61663b60c..23c215f965e 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -28,19 +28,22 @@ struct VnIpam { IpAddress ip_prefix; uint32_t plen; IpAddress default_gw; + // In case of TSN, we could have different addresses for default_gw & dns + IpAddress dns_server; bool installed; // is the route to send pkts to host installed bool dhcp_enable; std::string ipam_name; OperDhcpOptions oper_dhcp_options; VnIpam(const std::string& ip, uint32_t len, const std::string& gw, - bool dhcp, std::string &name, + const std::string& dns, bool dhcp, std::string &name, const std::vector &dhcp_options, const std::vector &host_routes) : plen(len), installed(false), dhcp_enable(dhcp), ipam_name(name) { boost::system::error_code ec; ip_prefix = IpAddress::from_string(ip, ec); default_gw = IpAddress::from_string(gw, ec); + dns_server = IpAddress::from_string(dns, ec); oper_dhcp_options.set_options(dhcp_options); oper_dhcp_options.set_host_routes(host_routes); } @@ -250,15 +253,15 @@ class VnTable : public AgentDBTable { static VnTable *vn_table_; bool IpamChangeNotify(std::vector &old_ipam, std::vector &new_ipam, VnEntry *vn); - void UpdateSubnetGateway(const VnIpam &old_ipam, const VnIpam &new_ipam, - VnEntry *vn); + void UpdateHostRoute(const IpAddress &old_address, + const IpAddress &new_address, VnEntry *vn); void AddIPAMRoutes(VnEntry *vn, VnIpam &ipam); void DelIPAMRoutes(VnEntry *vn, VnIpam &ipam); void DeleteAllIpamRoutes(VnEntry *vn); void AddSubnetRoute(VnEntry *vn, VnIpam &ipam); void DelSubnetRoute(VnEntry *vn, VnIpam &ipam); - void AddHostRouteForGw(VnEntry *vn, const VnIpam &ipam); - void DelHostRouteForGw(VnEntry *vn, const VnIpam &ipam); + void AddHostRoute(VnEntry *vn, const IpAddress &address); + void DelHostRoute(VnEntry *vn, const IpAddress &address); bool ChangeHandler(DBEntry *entry, const DBRequest *req); bool IsGatewayL2(const string &gateway) const; IFMapNode *FindTarget(IFMapAgentTable *table, IFMapNode *node, diff --git a/src/vnsw/agent/physical_devices/SConscript b/src/vnsw/agent/physical_devices/SConscript index 16f35b73a8d..6b126a55ce3 100644 --- a/src/vnsw/agent/physical_devices/SConscript +++ b/src/vnsw/agent/physical_devices/SConscript @@ -10,4 +10,6 @@ env = AgentEnv.Clone() env.SConscript('tables/SConscript', exports='AgentEnv', duplicate=0) env.SConscript('ovs_tor_agent/SConscript', exports='AgentEnv', duplicate=0) +env.SConscript('tsn/SConscript', exports='AgentEnv', duplicate=0) env.SConscript('test/SConscript', exports='AgentEnv', duplicate=0) +env.SConscript('tsn/SConscript', exports='AgentEnv', duplicate=0) diff --git a/src/vnsw/agent/physical_devices/tables/device_manager.cc b/src/vnsw/agent/physical_devices/tables/device_manager.cc index f9e8018fbb6..b296cb65845 100644 --- a/src/vnsw/agent/physical_devices/tables/device_manager.cc +++ b/src/vnsw/agent/physical_devices/tables/device_manager.cc @@ -14,6 +14,7 @@ #include #include #include +#include using boost::assign::map_list_of; using boost::assign::list_of; @@ -79,6 +80,9 @@ void PhysicalDeviceManager::RegisterDBClients() { physical_port_table_->RegisterDBClients(mgr); logical_port_table_->RegisterDBClients(mgr); physical_device_vn_table_->RegisterDBClients(mgr); + if (agent_->tsn_enabled()) { + tsn_vrf_listener_.reset(new TsnVrfListener(agent())); + } } void PhysicalDeviceManager::Init() { diff --git a/src/vnsw/agent/physical_devices/tables/device_manager.h b/src/vnsw/agent/physical_devices/tables/device_manager.h index 93fc0401f04..0b1112009ab 100644 --- a/src/vnsw/agent/physical_devices/tables/device_manager.h +++ b/src/vnsw/agent/physical_devices/tables/device_manager.h @@ -14,6 +14,7 @@ class PhysicalPortTable; class LogicalPortTable; class PhysicalDeviceVnTable; } +class TsnVrfListener; class PhysicalDeviceManager { public: @@ -43,6 +44,7 @@ class PhysicalDeviceManager { AGENT::PhysicalPortTable *physical_port_table_; AGENT::LogicalPortTable *logical_port_table_; AGENT::PhysicalDeviceVnTable *physical_device_vn_table_; + std::auto_ptr tsn_vrf_listener_; DISALLOW_COPY_AND_ASSIGN(PhysicalDeviceManager); }; diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.cc b/src/vnsw/agent/physical_devices/tables/physical_device.cc index 9b20973e589..4033c907692 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device.cc @@ -97,6 +97,11 @@ bool PhysicalDeviceEntry::Copy(const PhysicalDeviceData *data) { ret = true; } + if (management_ip_ != data->management_ip_) { + management_ip_ = data->management_ip_; + ret = true; + } + ManagementProtocol proto = FromString(data->protocol_); if (protocol_ != proto) { protocol_ = proto; diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index 7eb30efeef4..d44b864f909 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -38,7 +38,8 @@ const std::size_t PktTrace::kPktMaxTraceSize; //////////////////////////////////////////////////////////////////////////////// PktHandler::PktHandler(Agent *agent, PktModule *pkt_module) : - stats_(), agent_(agent), pkt_module_(pkt_module) { + stats_(), iid_(DBTableBase::kInvalidId), agent_(agent), + pkt_module_(pkt_module) { for (int i = 0; i < MAX_MODULES; ++i) { if (i == PktHandler::DHCP || i == PktHandler::DHCPV6 || i == PktHandler::DNS) @@ -51,6 +52,39 @@ PktHandler::PktHandler(Agent *agent, PktModule *pkt_module) : PktHandler::~PktHandler() { } +void PktHandler::RegisterDBClients() { + iid_ = agent_->interface_table()->Register( + boost::bind(&PktHandler::InterfaceNotify, this, _2)); +} + +void PktHandler::Shutdown() { + if (iid_ != DBTableBase::kInvalidId) { + agent_->interface_table()->Unregister(iid_); + iid_ = DBTableBase::kInvalidId; + } +} + +void PktHandler::InterfaceNotify(DBEntryBase *entry) { + Interface *itf = static_cast(entry); + if (itf->type() != Interface::VM_INTERFACE) + return; + + const VmInterface *vmitf = static_cast(entry); + if (vmitf->vm_mac().empty()) + return; + + ether_addr *eth_addr = ether_aton(vmitf->vm_mac().c_str()); + if (!eth_addr) return; + MacAddress address(*eth_addr); + + if (entry->IsDeleted()) { + mac_vm_binding_map_.erase(address); + } else { + // assumed that VM mac doesnt change + mac_vm_binding_map_.insert(MacVmBindingPair(address, itf)); + } +} + void PktHandler::Register(PktModuleName type, RcvQueueFunc cb) { enqueue_cb_.at(type) = cb; } @@ -80,24 +114,19 @@ void PktHandler::HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff){ pkt_info->agent_hdr = hdr; agent_->stats()->incr_pkt_exceptions(); - intf = agent_->interface_table()->FindInterface(hdr.ifindex); - if (intf == NULL) { - PKT_TRACE(Err, "Invalid interface index <" << hdr.ifindex << ">"); - agent_->stats()->incr_pkt_invalid_interface(); - goto enqueue; + if (!IsValidInterface(hdr.ifindex, &intf)) { + goto drop; } - if (intf->type() == Interface::VM_INTERFACE) { - VmInterface *vm_itf = static_cast(intf); - if (!vm_itf->layer3_forwarding()) { - PKT_TRACE(Err, "ipv4 not enabled for interface index <" << - hdr.ifindex << ">"); - agent_->stats()->incr_pkt_dropped(); + ParseUserPkt(pkt_info.get(), intf, pkt_type, pkt); + if (pkt_info->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) { + // In case of a control packet from a TOR served by us, the ifindex + // is modified to index of the VM interface; validate this interface. + if (!IsValidInterface(hdr.ifindex, &intf)) { goto drop; } } - ParseUserPkt(pkt_info.get(), intf, pkt_type, pkt); pkt_info->vrf = pkt_info->agent_hdr.vrf; // Handle ARP packet @@ -373,6 +402,12 @@ uint8_t *PktHandler::ParseUserPkt(PktInfo *pkt_info, Interface *intf, SetOuterIp(pkt_info, pkt); // IP Packets pkt = ParseIpPacket(pkt_info, pkt_type, pkt); + + // If it is a packet from TOR that we serve, dont parse any further + if (IsManagedTORPacket(intf, pkt_info, pkt_type, pkt)) { + return pkt; + } + // If tunneling is not enabled on interface or if it is a DHCP packet, // dont parse any further if (intf->IsTunnelEnabled() == false || IsDHCPPacket(pkt_info)) { @@ -467,6 +502,67 @@ bool PktHandler::IsDHCPPacket(PktInfo *pkt_info) { return false; } +// We can receive DHCP / DNS packets on physical port from TOR ports managed +// by a TOR services node. Check if the source mac is the mac address of a +// VM interface available in the node. +bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, + PktType::Type &pkt_type, uint8_t *pkt) { + if (intf->type() == Interface::PHYSICAL) { + if (pkt_type != PktType::UDP || pkt_info->dport != VXLAN_UDP_DEST_PORT) + return false; + + // Point to original L2 frame after the VXLAN header + pkt += 8; + + // get to the actual packet header + pkt_info->eth = (struct ether_header *) pkt; + pkt_info->ether_type = ntohs(pkt_info->eth->ether_type); + + if (pkt_info->ether_type == ETHERTYPE_VLAN) { + pkt = ((uint8_t *)pkt_info->eth) + sizeof(struct ether_header) + 4; + uint16_t *tmp = ((uint16_t *)pkt) - 1; + pkt_info->ether_type = ntohs(*tmp); + } else { + pkt = ((uint8_t *)pkt_info->eth) + sizeof(struct ether_header); + } + + ether_addr addr; + memcpy(addr.ether_addr_octet, pkt_info->eth->ether_shost, ETH_ALEN); + MacAddress address(addr); + MacVmBindingMap::iterator it = mac_vm_binding_map_.find(address); + if (it == mac_vm_binding_map_.end()) + return false; + + // Parse payload + if (pkt_info->ether_type == ETHERTYPE_ARP) { + pkt_info->arp = (ether_arp *) pkt; + pkt_type = PktType::ARP; + return true; + } + + // Identify NON-IP Packets + if (pkt_info->ether_type != ETHERTYPE_IP && + pkt_info->ether_type != ETHERTYPE_IPV6) { + pkt_info->data = pkt; + pkt_type = PktType::NON_IP; + return true; + } + + // IP Packets + pkt = ParseIpPacket(pkt_info, pkt_type, pkt); + + // update agent_hdr to reflect the VM interface data + // cmd_param is set to physical interface id + pkt_info->agent_hdr.cmd = AgentHdr::TRAP_TOR_CONTROL_PKT; + pkt_info->agent_hdr.cmd_param = pkt_info->agent_hdr.ifindex; + pkt_info->agent_hdr.ifindex = it->second->id(); + pkt_info->agent_hdr.vrf = it->second->vrf_id(); + return true; + } + + return false; +} + // Check if the packet is destined to the VM's default GW bool PktHandler::IsGwPacket(const Interface *intf, const IpAddress &dst_ip) { if (!intf || intf->type() != Interface::VM_INTERFACE) @@ -503,6 +599,28 @@ bool PktHandler::IsGwPacket(const Interface *intf, const IpAddress &dst_ip) { return false; } +bool PktHandler::IsValidInterface(uint16_t ifindex, Interface **interface) { + Interface *intf = agent_->interface_table()->FindInterface(ifindex); + if (intf == NULL) { + PKT_TRACE(Err, "Invalid interface index <" << ifindex << ">"); + agent_->stats()->incr_pkt_invalid_interface(); + return false; + } + + if (intf->type() == Interface::VM_INTERFACE) { + VmInterface *vm_itf = static_cast(intf); + if (!vm_itf->layer3_forwarding()) { + PKT_TRACE(Err, "layer3 not enabled for interface index <" << + ifindex << ">"); + agent_->stats()->incr_pkt_dropped(); + return false; + } + } + + *interface = intf; + return true; +} + void PktHandler::PktTraceIterate(PktModuleName mod, PktTraceCallback cb) { if (cb) { PktTrace &pkt(pkt_trace_.at(mod)); diff --git a/src/vnsw/agent/pkt/pkt_handler.h b/src/vnsw/agent/pkt/pkt_handler.h index b66de4d2ade..f39039fe5ed 100644 --- a/src/vnsw/agent/pkt/pkt_handler.h +++ b/src/vnsw/agent/pkt/pkt_handler.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #define DHCPV6_SERVER_PORT 547 #define DHCPV6_CLIENT_PORT 546 #define DNS_SERVER_PORT 53 +#define VXLAN_UDP_DEST_PORT 4789 #define IPv4_ALEN 4 #define ARP_TX_BUFF_LEN 128 @@ -89,6 +91,7 @@ struct AgentHdr { TRAP_ECMP_RESOLVE = AGENT_TRAP_ECMP_RESOLVE, TRAP_SOURCE_MISMATCH = AGENT_TRAP_SOURCE_MISMATCH, TRAP_HANDLE_DF = AGENT_TRAP_HANDLE_DF, + TRAP_TOR_CONTROL_PKT = AGENT_TRAP_TOR_CONTROL_PKT, INVALID = MAX_AGENT_HDR_COMMANDS }; @@ -222,6 +225,8 @@ class PktHandler { PktHandler(Agent *, PktModule *pkt_module); virtual ~PktHandler(); + void RegisterDBClients(); + void Shutdown(); void Register(PktModuleName type, RcvQueueFunc cb); @@ -253,6 +258,10 @@ class PktHandler { private: friend bool ::CallPktParse(PktInfo *pkt_info, uint8_t *ptr, int len); + typedef std::map MacVmBindingMap; + typedef std::pair MacVmBindingPair; + + void InterfaceNotify(DBEntryBase *entry); uint8_t *ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type, uint8_t *ptr); uint8_t *ParseUserPkt(PktInfo *pkt_info, Interface *intf, @@ -261,6 +270,9 @@ class PktHandler { int ParseMPLSoGRE(PktInfo *pkt_info, uint8_t *pkt); int ParseMPLSoUDP(PktInfo *pkt_info, uint8_t *pkt); bool IsDHCPPacket(PktInfo *pkt_info); + bool IsValidInterface(uint16_t ifindex, Interface **interface); + bool IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, + PktType::Type &pkt_type, uint8_t *pkt); // handlers for each module type boost::array enqueue_cb_; @@ -268,6 +280,11 @@ class PktHandler { PktStats stats_; boost::array pkt_trace_; + // map of VM mac addresses to VM Interface, used in TOR services node + // to identify the VM based on incoming packet's mac address. + MacVmBindingMap mac_vm_binding_map_; + DBTableBase::ListenerId iid_; + Agent *agent_; PktModule *pkt_module_; diff --git a/src/vnsw/agent/pkt/pkt_init.cc b/src/vnsw/agent/pkt/pkt_init.cc index 478bc9086dc..1bc4957e378 100644 --- a/src/vnsw/agent/pkt/pkt_init.cc +++ b/src/vnsw/agent/pkt/pkt_init.cc @@ -29,6 +29,7 @@ void PktModule::Init(bool run_with_vrouter) { boost::asio::io_service &io = *agent_->event_manager()->io_service(); pkt_handler_.reset(new PktHandler(agent_, this)); + pkt_handler_->RegisterDBClients(); if (control_interface_) { control_interface_->Init(pkt_handler_.get()); @@ -50,6 +51,8 @@ void PktModule::set_control_interface(ControlInterface *intf) { } void PktModule::Shutdown() { + pkt_handler_->Shutdown(); + flow_proto_->Shutdown(); flow_proto_.reset(NULL); diff --git a/src/vnsw/agent/services/dhcp_handler.cc b/src/vnsw/agent/services/dhcp_handler.cc index 84d7b7b054d..8a693d22ed5 100644 --- a/src/vnsw/agent/services/dhcp_handler.cc +++ b/src/vnsw/agent/services/dhcp_handler.cc @@ -549,7 +549,7 @@ bool DhcpHandler::FindLeaseData() { // Change client name to VM name; this is the name assigned to the VM config_.client_name_ = vm_itf_->vm_name(); FindDomainName(ip); - if (vm_itf_->ipv4_active()) { + if (vm_itf_->ipv4_active() || vm_itf_->sub_type() == VmInterface::TOR) { if (vm_itf_->fabric_port()) { InetUnicastRouteEntry *rt = InetUnicastAgentRouteTable::FindResolveRoute( @@ -579,7 +579,10 @@ bool DhcpHandler::FindLeaseData() { if (IsIp4SubnetMember(ip, ipam[i].ip_prefix.to_v4(), ipam[i].plen)) { Ip4Address default_gw = ipam[i].default_gw.to_v4(); - FillDhcpInfo(ip, ipam[i].plen, default_gw, default_gw); + Ip4Address dns_server = ipam[i].dns_server.to_v4(); + if (dns_server.is_unspecified()) + dns_server = default_gw; + FillDhcpInfo(ip, ipam[i].plen, default_gw, dns_server); return true; } } @@ -978,7 +981,10 @@ uint16_t DhcpHandler::FillDhcpResponse(const MacAddress &dest_mac, void DhcpHandler::SendDhcpResponse() { // TODO: If giaddr is set, what to do ? - in_addr_t src_ip = htonl(config_.gw_addr.to_v4().to_ulong()); + // In TSN, the source address for DHCP response should be the address + // in the subnet reserved for service node. Otherwise, it will be the + // GW address. dns_addr field has this address, use it as the source IP. + in_addr_t src_ip = htonl(config_.dns_addr.to_v4().to_ulong()); in_addr_t dest_ip = 0xFFFFFFFF; in_addr_t yiaddr = htonl(config_.ip_addr.to_v4().to_ulong()); in_addr_t siaddr = src_ip; @@ -1007,8 +1013,13 @@ void DhcpHandler::SendDhcpResponse() { UpdateStats(); FillDhcpResponse(dest_mac, src_ip, dest_ip, siaddr, yiaddr); - Send(GetInterfaceIndex(), pkt_info_->vrf, AgentHdr::TX_SWITCH, - PktHandler::DHCP); + uint16_t interface = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex(); + uint16_t command = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH; + Send(interface, pkt_info_->vrf, command, PktHandler::DHCP); } // Check if the option is requested by the client or not diff --git a/src/vnsw/agent/services/dhcpv6_handler.cc b/src/vnsw/agent/services/dhcpv6_handler.cc index 879ed9ed64e..596e31e727f 100644 --- a/src/vnsw/agent/services/dhcpv6_handler.cc +++ b/src/vnsw/agent/services/dhcpv6_handler.cc @@ -478,7 +478,10 @@ bool Dhcpv6Handler::FindLeaseData() { if (IsIp6SubnetMember(ip, ipam[i].ip_prefix.to_v6(), ipam[i].plen)) { Ip6Address default_gw = ipam[i].default_gw.to_v6(); - FillDhcpInfo(ip, ipam[i].plen, default_gw, default_gw); + Ip6Address dns_server = ipam[i].dns_server.to_v6(); + if (dns_server.is_unspecified()) + dns_server = default_gw; + FillDhcpInfo(ip, ipam[i].plen, default_gw, dns_server); return true; } } @@ -620,10 +623,19 @@ uint16_t Dhcpv6Handler::FillDhcpResponse(const MacAddress &dest_mac, void Dhcpv6Handler::SendDhcpResponse() { UpdateStats(); - FillDhcpResponse(MacAddress(pkt_info_->eth->ether_shost), config_.gw_addr.to_v6(), + // In TSN, the source address for DHCP response should be the address + // in the subnet reserved for service node. Otherwise, it will be the + // GW address. dns_addr field has this address, use it as the source IP. + FillDhcpResponse(MacAddress(pkt_info_->eth->ether_shost), + config_.dns_addr.to_v6(), pkt_info_->ip_saddr.to_v6()); - Send(GetInterfaceIndex(), pkt_info_->vrf, - AgentHdr::TX_SWITCH, PktHandler::DHCPV6); + uint16_t interface = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex(); + uint16_t command = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH; + Send(interface, pkt_info_->vrf, command, PktHandler::DHCPV6); } void Dhcpv6Handler::UpdateStats() { diff --git a/src/vnsw/agent/services/dns_handler.cc b/src/vnsw/agent/services/dns_handler.cc index d55b48039c3..52f3c037c40 100644 --- a/src/vnsw/agent/services/dns_handler.cc +++ b/src/vnsw/agent/services/dns_handler.cc @@ -797,8 +797,13 @@ void DnsHandler::SendDnsResponse() { (agent()->interface_table()->FindActiveEntry(&key)); if (pkt_itf) { UpdateStats(); - Send(pkt_info_->GetAgentHdr().ifindex, pkt_info_->vrf, - AgentHdr::TX_SWITCH, PktHandler::DNS); + uint16_t interface = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex(); + uint16_t command = + (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH; + Send(interface, pkt_info_->vrf, command, PktHandler::DNS); } else { agent()->GetDnsProto()->IncrStatsDrop(); } diff --git a/src/vnsw/agent/services/icmp_handler.cc b/src/vnsw/agent/services/icmp_handler.cc index c29fa986fb7..f41e81cd656 100644 --- a/src/vnsw/agent/services/icmp_handler.cc +++ b/src/vnsw/agent/services/icmp_handler.cc @@ -92,6 +92,11 @@ void IcmpHandler::SendResponse(VmInterface *vm_intf) { IcmpChecksum((char *)hdr, icmp_len_); pkt_info_->set_len(len); - Send(GetInterfaceIndex(), pkt_info_->vrf, AgentHdr::TX_SWITCH, - PktHandler::ICMP); + uint16_t interface = + ((pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + (uint16_t)pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex()); + uint16_t command = + ((pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? + AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH); + Send(interface, pkt_info_->vrf, command, PktHandler::ICMP); } diff --git a/src/vnsw/agent/services/test/dhcp_test.cc b/src/vnsw/agent/services/test/dhcp_test.cc index 0500eea7cd5..326e849b58b 100644 --- a/src/vnsw/agent/services/test/dhcp_test.cc +++ b/src/vnsw/agent/services/test/dhcp_test.cc @@ -1313,6 +1313,212 @@ TEST_F(DhcpTest, PortSpecificDhcpOptions) { Agent::GetInstance()->GetDhcpProto()->ClearStats(); } +// Check that DHCP requests from TOR are served +TEST_F(DhcpTest, DhcpTorRequestTest) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + {"vnet2", 2, "1.1.1.2", "00:00:00:02:02:02", 1, 2}, + }; + uint8_t options[] = { + DHCP_OPTION_MSG_TYPE, + DHCP_OPTION_HOST_NAME, + DHCP_OPTION_DOMAIN_NAME, + DHCP_OPTION_END + }; + DhcpProto::DhcpStats stats; + + ClearPktTrace(); + IpamInfo ipam_info[] = { + {"1.2.3.128", 27, "1.2.3.129", true}, + {"7.8.9.0", 24, "7.8.9.12", true}, + {"1.1.1.0", 24, "1.1.1.200", true}, + }; + char vdns_attr[] = "\n test.contrail.juniper.net\n true\n fixed\n 120\n \n"; + char ipam_attr[] = "\n virtual-dns-server\n vdns1\n \n"; + + CreateVmportEnv(input, 2, 0); + client->WaitForIdle(); + client->Reset(); + AddVDNS("vdns1", vdns_attr); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 3, ipam_attr, "vdns1"); + client->WaitForIdle(); + + // use the mac address of the VM as the source MAC + char mac1[MAC_LEN] = { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01 }; + memcpy(src_mac, mac1, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_REQUEST, options, 4); + int count = 0; + DHCP_CHECK (stats.acks < 1); + EXPECT_EQ(1U, stats.discover); + EXPECT_EQ(1U, stats.request); + EXPECT_EQ(1U, stats.offers); + EXPECT_EQ(1U, stats.acks); + + char mac2[MAC_LEN] = { 0x00, 0x00, 0x00, 0x02, 0x02, 0x02 }; + memcpy(src_mac, mac2, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_REQUEST, options, 4); + count = 0; + DHCP_CHECK (stats.acks < 2); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(2U, stats.acks); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_INFORM, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DECLINE, options, 4); + count = 0; + DHCP_CHECK (stats.decline < 1); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(1U, stats.inform); + EXPECT_EQ(1U, stats.decline); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(3U, stats.acks); + + char mac3[MAC_LEN] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + memcpy(src_mac, mac3, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4, true); + count = 0; + DHCP_CHECK (stats.errors < 1); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(1U, stats.inform); + EXPECT_EQ(1U, stats.decline); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(3U, stats.acks); + EXPECT_EQ(1U, stats.errors); + client->WaitForIdle(); + + DhcpInfo *sand = new DhcpInfo(); + Sandesh::set_response_callback( + boost::bind(&DhcpTest::CheckSandeshResponse, this, _1, + true, "", DHCP_RESPONSE_STRING, false, "", true)); + sand->HandleRequest(); + client->WaitForIdle(); + sand->Release(); + + client->Reset(); + DelIPAM("vn1", "vdns1"); + client->WaitForIdle(); + DelVDNS("vdns1"); + client->WaitForIdle(); + + client->Reset(); + DeleteVmportEnv(input, 2, 1, 0); + client->WaitForIdle(); + + Agent::GetInstance()->GetDhcpProto()->ClearStats(); +} + +// Check that DHCP requests from TOR are served +TEST_F(DhcpTest, DhcpTorRequestTest) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + {"vnet2", 2, "1.1.1.2", "00:00:00:02:02:02", 1, 2}, + }; + uint8_t options[] = { + DHCP_OPTION_MSG_TYPE, + DHCP_OPTION_HOST_NAME, + DHCP_OPTION_DOMAIN_NAME, + DHCP_OPTION_END + }; + DhcpProto::DhcpStats stats; + + ClearPktTrace(); + IpamInfo ipam_info[] = { + {"1.2.3.128", 27, "1.2.3.129", true}, + {"7.8.9.0", 24, "7.8.9.12", true}, + {"1.1.1.0", 24, "1.1.1.200", true}, + }; + char vdns_attr[] = "\n test.contrail.juniper.net\n true\n fixed\n 120\n \n"; + char ipam_attr[] = "\n virtual-dns-server\n vdns1\n \n"; + + CreateVmportEnv(input, 2, 0); + client->WaitForIdle(); + client->Reset(); + AddVDNS("vdns1", vdns_attr); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 3, ipam_attr, "vdns1"); + client->WaitForIdle(); + + // use the mac address of the VM as the source MAC + char mac1[MAC_LEN] = { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01 }; + memcpy(src_mac, mac1, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_REQUEST, options, 4); + int count = 0; + DHCP_CHECK (stats.acks < 1); + EXPECT_EQ(1U, stats.discover); + EXPECT_EQ(1U, stats.request); + EXPECT_EQ(1U, stats.offers); + EXPECT_EQ(1U, stats.acks); + + char mac2[MAC_LEN] = { 0x00, 0x00, 0x00, 0x02, 0x02, 0x02 }; + memcpy(src_mac, mac2, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_REQUEST, options, 4); + count = 0; + DHCP_CHECK (stats.acks < 2); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(2U, stats.acks); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_INFORM, options, 4); + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DECLINE, options, 4); + count = 0; + DHCP_CHECK (stats.decline < 1); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(1U, stats.inform); + EXPECT_EQ(1U, stats.decline); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(3U, stats.acks); + + char mac3[MAC_LEN] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + memcpy(src_mac, mac3, MAC_LEN); + + SendDhcp(fabric_interface_id(), 0x8000, DHCP_DISCOVER, options, 4, true); + count = 0; + DHCP_CHECK (stats.errors < 1); + EXPECT_EQ(2U, stats.discover); + EXPECT_EQ(2U, stats.request); + EXPECT_EQ(1U, stats.inform); + EXPECT_EQ(1U, stats.decline); + EXPECT_EQ(2U, stats.offers); + EXPECT_EQ(3U, stats.acks); + EXPECT_EQ(1U, stats.errors); + client->WaitForIdle(); + + DhcpInfo *sand = new DhcpInfo(); + Sandesh::set_response_callback( + boost::bind(&DhcpTest::CheckSandeshResponse, this, _1, + true, "", DHCP_RESPONSE_STRING, false, "", true)); + sand->HandleRequest(); + client->WaitForIdle(); + sand->Release(); + + client->Reset(); + DelIPAM("vn1", "vdns1"); + client->WaitForIdle(); + DelVDNS("vdns1"); + client->WaitForIdle(); + + client->Reset(); + DeleteVmportEnv(input, 2, 1, 0); + client->WaitForIdle(); + + Agent::GetInstance()->GetDhcpProto()->ClearStats(); +} + TEST_F(DhcpTest, DhcpEnableTestForward) { DhcpEnableTest(true); } diff --git a/src/vnsw/agent/uve/agent_stats_collector.cc b/src/vnsw/agent/uve/agent_stats_collector.cc index 8cd9ab1cf0f..289b446f62e 100644 --- a/src/vnsw/agent/uve/agent_stats_collector.cc +++ b/src/vnsw/agent/uve/agent_stats_collector.cc @@ -57,7 +57,6 @@ void AgentStatsCollector::SendVrfStatsBulkGet() { encoder.set_h_op(sandesh_op::DUMP); encoder.set_vsr_rid(0); encoder.set_vsr_family(AF_INET); - encoder.set_vsr_type(RT_UCAST); encoder.set_vsr_marker(vrf_stats_sandesh_ctx_.get()->marker_id()); SendRequest(encoder, VrfStatsType); } diff --git a/src/vnsw/agent/uve/agent_stats_sandesh_context.cc b/src/vnsw/agent/uve/agent_stats_sandesh_context.cc index 086d58966af..f8785a55ed8 100644 --- a/src/vnsw/agent/uve/agent_stats_sandesh_context.cc +++ b/src/vnsw/agent/uve/agent_stats_sandesh_context.cc @@ -103,10 +103,10 @@ void AgentStatsSandeshContext::VrfStatsMsgHandler(vr_vrf_stats_req *req) { stats->prev_gre_mpls_tunnels = req->get_vsr_gre_mpls_tunnels(); stats->prev_ecmp_composites = req->get_vsr_ecmp_composites(); stats->prev_l2_mcast_composites = req->get_vsr_l2_mcast_composites(); - stats->prev_l3_mcast_composites = req->get_vsr_l3_mcast_composites(); + //stats->prev_l3_mcast_composites = req->get_vsr_l3_mcast_composites(); stats->prev_fabric_composites = req->get_vsr_fabric_composites(); - stats->prev_multi_proto_composites = - req->get_vsr_multi_proto_composites(); + //stats->prev_multi_proto_composites = + // req->get_vsr_multi_proto_composites(); stats->prev_encaps = req->get_vsr_encaps(); stats->prev_l2_encaps = req->get_vsr_l2_encaps(); } else { @@ -125,12 +125,12 @@ void AgentStatsSandeshContext::VrfStatsMsgHandler(vr_vrf_stats_req *req) { stats->prev_ecmp_composites; stats->l2_mcast_composites = req->get_vsr_l2_mcast_composites() - stats->prev_l2_mcast_composites; - stats->l3_mcast_composites = req->get_vsr_l3_mcast_composites() - - stats->prev_l3_mcast_composites; + //stats->l3_mcast_composites = req->get_vsr_l3_mcast_composites() - + // stats->prev_l3_mcast_composites; stats->fabric_composites = req->get_vsr_fabric_composites() - stats->prev_fabric_composites; - stats->multi_proto_composites = req->get_vsr_multi_proto_composites() - - stats->prev_multi_proto_composites; + //stats->multi_proto_composites = req->get_vsr_multi_proto_composites() - + // stats->prev_multi_proto_composites; /* Update the last read values from Kernel in the following fields. * This will be used to update prev_* fields on receiving vrf delete @@ -144,11 +144,11 @@ void AgentStatsSandeshContext::VrfStatsMsgHandler(vr_vrf_stats_req *req) { stats->k_gre_mpls_tunnels = req->get_vsr_gre_mpls_tunnels(); stats->k_udp_mpls_tunnels = req->get_vsr_udp_mpls_tunnels(); stats->k_l2_mcast_composites = req->get_vsr_l2_mcast_composites(); - stats->k_l3_mcast_composites = req->get_vsr_l3_mcast_composites(); + //stats->k_l3_mcast_composites = req->get_vsr_l3_mcast_composites(); stats->k_ecmp_composites = req->get_vsr_ecmp_composites(); stats->k_fabric_composites = req->get_vsr_fabric_composites(); - stats->k_multi_proto_composites = - req->get_vsr_multi_proto_composites(); + //stats->k_multi_proto_composites = + // req->get_vsr_multi_proto_composites(); stats->k_encaps = req->get_vsr_encaps(); stats->k_l2_encaps = req->get_vsr_l2_encaps(); } From 527b467fe89cd033c9cef7c690f0111a8f27369f Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 21 Oct 2014 22:25:42 -0700 Subject: [PATCH 018/218] fix initializing ovsdb_entry row pointer for locator Handle reuse of physical locator for multicast remote mac. --- .../ovsdb_client/logical_switch_ovsdb.cc | 24 +++++++++++++++---- .../ovsdb_client/ovsdb_wrapper.c | 12 ++++++---- .../ovsdb_client/ovsdb_wrapper.h | 2 +- .../ovsdb_client/physical_locator_ovsdb.cc | 1 + 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index 27248b4e51c..a5a78eed70a 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -7,6 +7,7 @@ extern "C" { }; #include #include +#include #include #include @@ -50,8 +51,21 @@ void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) { vxlan_id_); /* Add remote multicast entry if not already present */ if (mcast_remote_row_ == NULL) { + std::string dest_ip = table_->client_idl()->tsn_ip().to_string(); + PhysicalLocatorTable *pl_table = + table_->client_idl()->physical_locator_table(); + PhysicalLocatorEntry pl_key(pl_table, dest_ip); + /* + * we don't take reference to physical locator, just use if locator + * is existing or we will create a new one. + */ + PhysicalLocatorEntry *pl_entry = + static_cast(pl_table->Find(&pl_key)); + struct ovsdb_idl_row *pl_row = NULL; + if (pl_entry) + pl_row = pl_entry->ovs_entry(); ovsdb_wrapper_add_mcast_mac_remote(txn, NULL, "unknown-dst", row, - table_->client_idl()->tsn_ip().to_string().c_str()); + pl_row, dest_ip.c_str()); } if (old_mcast_remote_row_ != NULL) { ovsdb_wrapper_delete_mcast_mac_remote(old_mcast_remote_row_); @@ -184,13 +198,13 @@ void LogicalSwitchTable::OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op op, entry = static_cast(Find(&key)); } if (op == OvsdbClientIdl::OVSDB_DEL) { - OVSDB_TRACE(Trace, "Delete : Local Mcast MAC" + std::string(mac) + + OVSDB_TRACE(Trace, "Delete : Local Mcast MAC " + std::string(mac) + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = NULL; } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - OVSDB_TRACE(Trace, "Add : Local Mcast MAC" + std::string(mac) + + OVSDB_TRACE(Trace, "Add : Local Mcast MAC " + std::string(mac) + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = row; @@ -210,7 +224,7 @@ void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, entry = static_cast(Find(&key)); } if (op == OvsdbClientIdl::OVSDB_DEL) { - OVSDB_TRACE(Trace, "Delete : Remote Mcast MAC" + std::string(mac) + + OVSDB_TRACE(Trace, "Delete : Remote Mcast MAC " + std::string(mac) + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { if (entry->old_mcast_remote_row_ == row) @@ -219,7 +233,7 @@ void LogicalSwitchTable::OvsdbMcastRemoteMacNotify(OvsdbClientIdl::Op op, entry->mcast_remote_row_ = NULL; } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - OVSDB_TRACE(Trace, "Add : Remote Mcast MAC" + std::string(mac) + + OVSDB_TRACE(Trace, "Add : Remote Mcast MAC " + std::string(mac) + ", logical switch " + (ls ? std::string(ls) : "")); if (entry) { entry->mcast_local_row_ = row; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index 25687333164..a1bfe89b111 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -456,7 +456,7 @@ ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row) void ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, - const char *dst_ip) + struct ovsdb_idl_row *pl, const char *dst_ip) { struct vteprec_mcast_macs_remote *mcast = row ? CONTAINER_OF(row, struct vteprec_mcast_macs_remote, header_) : NULL; @@ -470,9 +470,13 @@ ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, struct vteprec_logical_switch *l_switch = ls ? CONTAINER_OF(ls, struct vteprec_logical_switch, header_) : NULL; vteprec_mcast_macs_remote_set_logical_switch(mcast, l_switch); - struct vteprec_physical_locator *p = vteprec_physical_locator_insert(txn); - vteprec_physical_locator_set_dst_ip(p, dst_ip); - vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + struct vteprec_physical_locator *p = + pl ? CONTAINER_OF(pl, struct vteprec_physical_locator, header_) : NULL; + if (p == NULL) { + p = vteprec_physical_locator_insert(txn); + vteprec_physical_locator_set_dst_ip(p, dst_ip); + vteprec_physical_locator_set_encapsulation_type(p, "vxlan_over_ipv4"); + } vteprec_physical_locator_set_set_locators(l_set, &p, 1); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index 6bd01f3cd1e..c088b99d4f6 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -93,7 +93,7 @@ ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row); /* multicast mac remote */ void ovsdb_wrapper_add_mcast_mac_remote(struct ovsdb_idl_txn *txn, struct ovsdb_idl_row *row, const char *mac, struct ovsdb_idl_row *ls, - const char *dst_ip); + struct ovsdb_idl_row *pl, const char *dst_ip); void ovsdb_wrapper_delete_mcast_mac_remote(struct ovsdb_idl_row *row); char *ovsdb_wrapper_mcast_mac_remote_mac(struct ovsdb_idl_row *row); char * diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc index 7143b80a1be..d19f2f9a804 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc @@ -55,6 +55,7 @@ void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, } else if (op == OvsdbClientIdl::OVSDB_ADD) { if (entry == NULL) { entry = static_cast(Create(&key)); + entry->ovs_entry_ = row; OVSDB_TRACE(Trace, "Add received for Physical Locator " + entry->dip_); } From 810a7da6a308e34b365382d310bbe3a56028e1df Mon Sep 17 00:00:00 2001 From: manishsingh Date: Tue, 21 Oct 2014 22:34:01 -0700 Subject: [PATCH 019/218] Add TSN directory and tsn_vrf_listener. --- src/vnsw/agent/physical_devices/SConscript | 1 - .../agent/physical_devices/tsn/SConscript | 13 ++++ .../physical_devices/tsn/tsn_vrf_listener.cc | 65 +++++++++++++++++++ .../physical_devices/tsn/tsn_vrf_listener.h | 22 +++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/vnsw/agent/physical_devices/tsn/SConscript create mode 100644 src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc create mode 100644 src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.h diff --git a/src/vnsw/agent/physical_devices/SConscript b/src/vnsw/agent/physical_devices/SConscript index 6b126a55ce3..d699b73fb94 100644 --- a/src/vnsw/agent/physical_devices/SConscript +++ b/src/vnsw/agent/physical_devices/SConscript @@ -12,4 +12,3 @@ env.SConscript('tables/SConscript', exports='AgentEnv', duplicate=0) env.SConscript('ovs_tor_agent/SConscript', exports='AgentEnv', duplicate=0) env.SConscript('tsn/SConscript', exports='AgentEnv', duplicate=0) env.SConscript('test/SConscript', exports='AgentEnv', duplicate=0) -env.SConscript('tsn/SConscript', exports='AgentEnv', duplicate=0) diff --git a/src/vnsw/agent/physical_devices/tsn/SConscript b/src/vnsw/agent/physical_devices/tsn/SConscript new file mode 100644 index 00000000000..da40bb9356f --- /dev/null +++ b/src/vnsw/agent/physical_devices/tsn/SConscript @@ -0,0 +1,13 @@ +# +# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. +# + +# -*- mode: python; -*- + +import sys +Import('AgentEnv') +env = AgentEnv.Clone() + +tsn = env.Library('tsn', + ['tsn_vrf_listener.cc', + ]) diff --git a/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc new file mode 100644 index 00000000000..ae38c333c8a --- /dev/null +++ b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +TsnVrfListener::TsnVrfListener(Agent *agent) : agent_(agent) { + vrf_table_listener_id_ = agent->vrf_table()->Register( + boost::bind(&TsnVrfListener::VrfNotify, this, _2)); +} + +TsnVrfListener::~TsnVrfListener() { + agent_->vrf_table()->Unregister(vrf_table_listener_id_); +} + +void TsnVrfListener::VrfNotify(DBEntryBase *entry) { + VrfEntry *vrf = static_cast(entry); + if (vrf->GetName() == agent_->fabric_vrf_name()) + return; + MacAddress address(agent_->vhost_interface()->mac()); + + if (entry->IsDeleted()) { + Layer2AgentRouteTable::Delete(agent_->local_peer(), vrf->GetName(), -1, + address); + return; + } + + std::string vn_name; + GetVnName(vrf, &vn_name); + Layer2AgentRouteTable::AddLayer2ReceiveRoute(agent_->local_peer(), + vrf->GetName(), vn_name, + address, + "pkt0", true); + //Add TSN route + boost::system::error_code ec; + IpAddress tsn_addr = IpAddress::from_string(agent_->tsn_ip_1(), ec).to_v4(); + IpAddress tsn_gw_addr = IpAddress::from_string(agent_->tsn_ip_2(), ec).to_v4(); + SecurityGroupList sg; + PathPreference pref; + ControllerVmRoute *data = + ControllerVmRoute::MakeControllerVmRoute(agent_->local_peer(), + Agent::GetInstance()->fabric_vrf_name(), + Agent::GetInstance()->router_id(), + Agent::GetInstance()->fabric_vrf_name(), + tsn_gw_addr.to_v4(), TunnelType::VxlanType(), + 4, "", sg, pref); + + InetUnicastAgentRouteTable::AddRemoteVmRouteReq(agent_->local_peer(), + Agent::GetInstance()->fabric_vrf_name(), + tsn_addr, 32, + data); +} + +// TODO: change this +void TsnVrfListener::GetVnName(VrfEntry *vrf, std::string *vn_name) { + std::size_t pos = vrf->GetName().find_last_of(":"); + if (pos == std::string::npos) + return; + *vn_name = vrf->GetName().substr(0, pos - 1); +} diff --git a/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.h b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.h new file mode 100644 index 00000000000..1d1f6d2adb0 --- /dev/null +++ b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef tsn_vrf_listener_h_ +#define tsn_vrf_listener_h_ + +class TsnVrfListener { +public: + TsnVrfListener(Agent *agent); + virtual ~TsnVrfListener(); + void VrfNotify(DBEntryBase *entry); + +private: + void GetVnName(VrfEntry *vrf, std::string *vn_name); + + Agent *agent_; + DBTableBase::ListenerId vrf_table_listener_id_; + DISALLOW_COPY_AND_ASSIGN(TsnVrfListener); +}; + +#endif // tsn_vrf_listener_h_ From 47f79bf8c81307fa07800fc7ad4c78681312c1ed Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 21 Oct 2014 22:44:28 -0700 Subject: [PATCH 020/218] fixing sub directory inclusion and compilation for tor-agent --- src/vnsw/agent/SConscript | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vnsw/agent/SConscript b/src/vnsw/agent/SConscript index 67f29cfc02c..4db96fdb320 100644 --- a/src/vnsw/agent/SConscript +++ b/src/vnsw/agent/SConscript @@ -294,8 +294,7 @@ subdirs = [ 'ksync', 'openstack', 'oper', - 'physical_devices/tables', - 'physical_devices/tsn', + 'physical_devices', 'pkt', 'services', 'test', From f111868a0e800c59b667346c4bc9510f5a6da3f1 Mon Sep 17 00:00:00 2001 From: Nipa Kumar Date: Mon, 29 Sep 2014 15:34:35 -0700 Subject: [PATCH 021/218] Derive ip family from prefix while provisioning static routes Change-Id: I95a9bb9f5a4200ce60e26ac0300f893d474ada0c --- src/config/utils/provision_static_route.py | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/config/utils/provision_static_route.py b/src/config/utils/provision_static_route.py index 2f64b151320..a00c4b92e17 100644 --- a/src/config/utils/provision_static_route.py +++ b/src/config/utils/provision_static_route.py @@ -6,11 +6,13 @@ import sys import argparse import ConfigParser +import netaddr from vnc_api.vnc_api import * from vnc_api.gen.resource_xsd import RouteType from vnc_api.gen.resource_xsd import RouteTableType from vnc_api.gen.resource_client import InterfaceRouteTable +from netaddr import * class StaticRouteProvisioner(object): @@ -30,7 +32,22 @@ def __init__(self, args_str=None): prefix = self._args.prefix vmi_id_got = self._args.virtual_machine_interface_id route_table_name = self._args.route_table_name - route_table_family = self._args.route_table_family + + try: + ip_nw = IPNetwork(prefix) + except AddrFormatError: + print 'Invalid ip address format' + sys.exit(1) + + if ip_nw.ip.version is 4: + route_table_name = route_table_name + 'v4' + route_table_family = 'v4' + elif ip_nw.ip.version is 6: + route_table_name = route_table_name + 'v6' + route_table_family = 'v6' + else: + print 'Invalid ip prefix' + sys.exit(1) project_fq_name_str = 'default-domain:'+ self._args.tenant_name project_fq_name = project_fq_name_str.split(':') @@ -120,7 +137,6 @@ def _parse_args(self, args_str): --prefix 2.2.2.0/24 --virtual_machine_interface_id 242717c9-8e78-4c67-94a8-5fbef1f2f096 --route_table_name "MyRouteTable" - --route_table_family "v4" --tenant_name "admin" --oper ''' @@ -139,7 +155,6 @@ def _parse_args(self, args_str): 'oper': 'add', 'control_names': [], 'route_table_name': 'CustomRouteTable', - 'route_table_family': 'v4', } ksopts = { 'user': 'user1', @@ -178,15 +193,13 @@ def _parse_args(self, args_str): parser.add_argument( "--virtual_machine_interface_id", help="Next hop which is the UUID of the VMI(aka port-id)") parser.add_argument( - "--tenant_name", help="Tenamt name for keystone admin user") + "--tenant_name", help="Tenant name for keystone admin user") parser.add_argument( "--user", help="Name of keystone admin user") parser.add_argument( "--password", help="Password of keystone admin user") parser.add_argument( "--route_table_name", help="Route Table name. Default : CustomRouteTable") - parser.add_argument( - "--route_table_family", help="Route Table family, v4 or v6. Default : v4") self._args = parser.parse_args(remaining_argv) From 42122a69935ba21c4565b725ba1300efb08772d4 Mon Sep 17 00:00:00 2001 From: arvindvis Date: Fri, 3 Oct 2014 15:14:44 -0700 Subject: [PATCH 022/218] This bug adds the ModuleId from the Messages into the field names stats table, so that it can be queried to get a list of ModuleId's occuring in any time range. Closes-Bug:#1360414 Change-Id: I8256ff794850bd321ad8fe543fa83b8356c5f21b --- src/analytics/db_handler.cc | 71 +++++++++++++++------------ src/analytics/db_handler.h | 7 ++- src/analytics/ruleeng.cc | 2 +- src/analytics/test/db_handler_test.cc | 35 ++++++++++--- 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/analytics/db_handler.cc b/src/analytics/db_handler.cc index c5339a9a259..1ad871ef052 100644 --- a/src/analytics/db_handler.cc +++ b/src/analytics/db_handler.cc @@ -447,23 +447,45 @@ void DbHandler::MessageTableInsert(const VizMsg *vmsgp) { DB_LOG(ERROR, "Failed to parse:" << s); } } + /* - * Insert the message types in the stat table + * Insert the message types,module_id in the stat table * Construct the atttributes,attrib_tags beofore inserting * to the StatTableInsert */ - uint64_t temp_u64; + if ((stype == SandeshType::SYSLOG) || (stype == SandeshType::SYSTEM)) { + //Insert only if sandesh type is a SYSTEM LOG or SYSLOG + //Insert into the FieldNames stats table entries for Messagetype and Module ID + FieldNamesTableInsert(g_viz_constants.COLLECTOR_GLOBAL_TABLE, + ":Messagetype", message_type, header.get_Timestamp()); + FieldNamesTableInsert(g_viz_constants.COLLECTOR_GLOBAL_TABLE, + ":ModuleId", header.get_Module(), header.get_Timestamp()); + } +} + +/* + * This function takes field name and field value as arguments and inserts + * into the FieldNames stats table + */ +void DbHandler::FieldNamesTableInsert(const std::string& table_prefix, + const std::string& field_name, const std::string& field_val, + uint64_t timestamp) { + /* + * Insert the message types in the stat table + * Construct the atttributes,attrib_tags before inserting + * to the StatTableInsert + */ DbHandler::TagMap tmap; DbHandler::AttribMap amap; DbHandler::Var pv; DbHandler::AttribMap attribs; - std::string name_val = string(g_viz_constants.COLLECTOR_GLOBAL_TABLE); - name_val.append(":Messagetype"); - pv = name_val; + std::string table_name(table_prefix); + table_name.append(field_name); + pv = table_name; tmap.insert(make_pair("name", make_pair(pv, amap))); attribs.insert(make_pair(string("name"), pv)); string sattrname("fields.value"); - pv = string(message_type); + pv = string(field_val); attribs.insert(make_pair(sattrname,pv)); //pv = string(header.get_Source()); @@ -473,8 +495,7 @@ void DbHandler::MessageTableInsert(const VizMsg *vmsgp) { tmap.insert(make_pair("Source",make_pair(pv,amap))); attribs.insert(make_pair(string("Source"),pv)); - temp_u64 = header.get_Timestamp(); - StatTableInsert(temp_u64, "FieldNames","fields",tmap,attribs); + StatTableInsert(timestamp, "FieldNames","fields",tmap,attribs); } @@ -489,7 +510,7 @@ void DbHandler::GetRuleMap(RuleMap& rulemap) { * value: uuid (of the corresponding global message) */ void DbHandler::ObjectTableInsert(const std::string &table, const std::string &objectkey_str, - uint64_t ×tamp, const boost::uuids::uuid& unm) { + uint64_t ×tamp, const boost::uuids::uuid& unm, const VizMsg *vmsgp) { uint32_t T2(timestamp >> g_viz_constants.RowTimeInBits); uint32_t T1(timestamp & g_viz_constants.RowTimeInMask); @@ -541,29 +562,17 @@ void DbHandler::ObjectTableInsert(const std::string &table, const std::string &o return; } - /* - * Inserting into the stat table - */ - DbHandler::TagMap tmap; - DbHandler::AttribMap amap; - DbHandler::Var pv; - DbHandler::AttribMap attribs; - std::string name_val = string(table); - name_val.append(":Objecttype"); - pv = name_val; - tmap.insert(make_pair("name", make_pair(pv, amap))); - attribs.insert(make_pair(string("name"), pv)); - string sattrname("fields.value"); - pv = string(objectkey_str); - attribs.insert(make_pair(sattrname,pv)); - - pv = string(col_name_); - tmap.insert(make_pair("Source",make_pair(pv,amap))); - attribs.insert(make_pair(string("Source"),pv)); - - StatTableInsert(timestamp, "FieldNames","fields",tmap,attribs); + /* + * Inserting into the stat table + */ + const SandeshHeader &header(vmsgp->msg->GetHeader()); + const std::string &message_type(vmsgp->msg->GetMessageType()); + //Insert into the FieldNames stats table entries for Messagetype and Module ID + FieldNamesTableInsert(table, ":Objecttype", objectkey_str, timestamp); + FieldNamesTableInsert(table, ":Messagetype", message_type, timestamp); + FieldNamesTableInsert(table, ":ModuleId", header.get_Module(), + timestamp); } - } bool DbHandler::StatTableWrite(uint32_t t2, diff --git a/src/analytics/db_handler.h b/src/analytics/db_handler.h index 9e9a4a6d3de..b90f9f7b7f1 100644 --- a/src/analytics/db_handler.h +++ b/src/analytics/db_handler.h @@ -95,11 +95,14 @@ class DbHandler { const boost::uuids::uuid& unm, const std::string keyword); virtual void MessageTableInsert(const VizMsg *vmsgp); void MessageTableOnlyInsert(const VizMsg *vmsgp); - + void FieldNamesTableInsert(const std::string& table_name, + const std::string& field_name, const std::string& field_val, + uint64_t timestamp); void GetRuleMap(RuleMap& rulemap); void ObjectTableInsert(const std::string &table, const std::string &rowkey, - uint64_t ×tamp, const boost::uuids::uuid& unm); + uint64_t ×tamp, const boost::uuids::uuid& unm, + const VizMsg *vmsgp); static std::vector StatTableSelectStr( const std::string& statName, const std::string& statAttr, diff --git a/src/analytics/ruleeng.cc b/src/analytics/ruleeng.cc index 8a1e6738446..fb1ae4d0950 100644 --- a/src/analytics/ruleeng.cc +++ b/src/analytics/ruleeng.cc @@ -122,7 +122,7 @@ void Ruleeng::handle_object_log(const pugi::xml_node& parent, const VizMsg *rmsg uint64_t timestamp(header.get_Timestamp()); for (it = keymap.begin(); it != keymap.end(); it++) { db->ObjectTableInsert(it->first, it->second, - timestamp, rmsg->unm); + timestamp, rmsg->unm, rmsg); } for (pugi::xml_node node = parent.first_child(); node; node = node.next_sibling()) { diff --git a/src/analytics/test/db_handler_test.cc b/src/analytics/test/db_handler_test.cc index c67ba455ca1..bb875ce36a3 100644 --- a/src/analytics/test/db_handler_test.cc +++ b/src/analytics/test/db_handler_test.cc @@ -213,6 +213,7 @@ TEST_F(DbHandlerTest, MessageTableInsertTest) { hdr.set_InstanceId("Test"); hdr.set_NodeType("Test"); hdr.set_Timestamp(UTCTimestampUsec()); + hdr.set_Type(SandeshType::SYSTEM); std::string xmlmessage = "src/analytics/test/viz_collector_test.cc80sat2string101101101"; SandeshXMLMessageTest *msg = dynamic_cast( @@ -244,7 +245,7 @@ TEST_F(DbHandlerTest, MessageTableInsertTest) { (GenDb::NewCol(g_viz_constants.VERSION, static_cast(0))) (GenDb::NewCol(g_viz_constants.SANDESH_TYPE, - static_cast(0))) + static_cast(SandeshType::SYSTEM))) (GenDb::NewCol(g_viz_constants.DATA, xmlmessage)); EXPECT_CALL(*dbif_mock(), @@ -328,13 +329,23 @@ TEST_F(DbHandlerTest, MessageTableInsertTest) { .Times(1) .WillOnce(Return(true)); + EXPECT_CALL(*dbif_mock(), + Db_AddColumnProxy( + Pointee( + AllOf(Field(&GenDb::ColList::cfname_, g_viz_constants.MESSAGE_TABLE_KEYWORD), + _, + Field(&GenDb::ColList::columns_, + idx_expected_vector))))) + .Times(2) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*dbif_mock(), Db_AddColumnProxy( Pointee( AllOf(Field(&GenDb::ColList::cfname_, g_viz_constants.STATS_TABLE_BY_STR_TAG), _, _)))) - .Times(2) + .Times(4) .WillRepeatedly(Return(true)); db_handler()->MessageTableInsert(&vmsgp); @@ -350,6 +361,13 @@ TEST_F(DbHandlerTest, ObjectTableInsertTest) { boost::uuids::uuid unm(rgen_()); std::string table("ObjectTableInsertTest"); std::string rowkey_str("ObjectTableInsertTestRowkey"); + std::string xmlmessage = "0000000020field1_value21string223"; + SandeshXMLMessageTest *msg = dynamic_cast( + builder_->Create( + reinterpret_cast(xmlmessage.c_str()), + xmlmessage.size())); + msg->SetHeader(hdr); + VizMsg vmsgp(msg, unm); { DbDataValueVec *colname(new DbDataValueVec()); @@ -425,8 +443,8 @@ TEST_F(DbHandlerTest, ObjectTableInsertTest) { Pointee( AllOf(Field(&GenDb::ColList::cfname_, g_viz_constants.STATS_TABLE_BY_STR_TAG), Field(&GenDb::ColList::rowkey_, rowkey),_)))) - .Times(1) - .WillOnce(Return(true)); + .Times(3) + .WillRepeatedly(Return(true)); } { @@ -454,12 +472,13 @@ TEST_F(DbHandlerTest, ObjectTableInsertTest) { Pointee( AllOf(Field(&GenDb::ColList::cfname_, g_viz_constants.STATS_TABLE_BY_STR_TAG), Field(&GenDb::ColList::rowkey_, rowkey),_)))) - .Times(1) - .WillOnce(Return(true)); + .Times(3) + .WillRepeatedly(Return(true)); } - - db_handler()->ObjectTableInsert(table, rowkey_str, timestamp, unm); + db_handler()->ObjectTableInsert(table, rowkey_str, timestamp, unm, &vmsgp); + vmsgp.msg = NULL; + delete msg; } TEST_F(DbHandlerTest, FlowTableInsertTest) { From e34fd512fc20957cca2470e6e40a9cdc079851e1 Mon Sep 17 00:00:00 2001 From: Rudra Rugge Date: Wed, 15 Oct 2014 14:51:54 -0700 Subject: [PATCH 023/218] Schema change to link loadbalancer pool to VMI Add a link from loadbalancer pool to virtual machine interface(VMI). VMI is linked to a logical interface of a physical router where the configuration is stored. Change-Id: I1f708e12ad0bef87c33da34b189d1c86574c4b81 Closes-Bug: #1381775 --- src/schema/loadbalancer.xsd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/schema/loadbalancer.xsd b/src/schema/loadbalancer.xsd index 28f5949911d..664fd34c812 100644 --- a/src/schema/loadbalancer.xsd +++ b/src/schema/loadbalancer.xsd @@ -56,6 +56,11 @@ Link('loadbalancer-pool-service-instance', 'loadbalancer-pool', 'service-instance', ['ref']) --> + + + From 58e67c39beb90dfb0f0d0a4b399eb91065bdbd68 Mon Sep 17 00:00:00 2001 From: Sachin Bansal Date: Wed, 15 Oct 2014 14:56:43 -0700 Subject: [PATCH 024/218] If the API client updates a network object with subnets and does not send a subnet_uuid, we were allocating a new UUID. If the subnet already exists, we should reuse the subnet_uuid. Now, we read from cassandra before generating a new UUID. Change-Id: I13426663c8a2a8e79fbf170dffb81c726506cee1 Closes-Bug: 1381779 (cherry picked from commit c2f71af5f2e9a6f31ce65e48c0e4a4c62e82f0c8) --- src/config/api-server/vnc_cfg_ifmap.py | 28 ++++++++++++++++---------- src/config/api-server/vnc_cfg_types.py | 15 ++------------ 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/config/api-server/vnc_cfg_ifmap.py b/src/config/api-server/vnc_cfg_ifmap.py index 25e16cd7ba2..3edccccf4f3 100644 --- a/src/config/api-server/vnc_cfg_ifmap.py +++ b/src/config/api-server/vnc_cfg_ifmap.py @@ -1269,17 +1269,23 @@ def match_uuid(self, obj_dict, obj_uuid): return False # end match_uuid - def _update_subnet_uuid(self, vn_dict): - vn_uuid = vn_dict['uuid'] + def update_subnet_uuid(self, vn_dict, do_update=False): + vn_uuid = vn_dict.get('uuid') - def _get_subnet_key(subnet): + def _read_subnet_uuid(subnet): + if vn_uuid is None: + return None pfx = subnet['subnet']['ip_prefix'] pfx_len = subnet['subnet']['ip_prefix_len'] network = IPNetwork('%s/%s' % (pfx, pfx_len)) - return '%s %s/%s' % (vn_uuid, str(network.ip), pfx_len) + subnet_key = '%s %s/%s' % (vn_uuid, str(network.ip), pfx_len) + try: + return self.useragent_kv_retrieve(subnet_key) + except NoUserAgentKey: + return None - ipam_refs = vn_dict['network_ipam_refs'] + ipam_refs = vn_dict.get('network_ipam_refs', []) updated = False for ipam in ipam_refs: vnsn = ipam['attr'] @@ -1288,15 +1294,15 @@ def _get_subnet_key(subnet): if subnet.get('subnet_uuid'): continue - subnet_key = _get_subnet_key(subnet) - subnet_uuid = self.useragent_kv_retrieve(subnet_key) + subnet_uuid = _read_subnet_uuid(subnet) or str(uuid.uuid4()) subnet['subnet_uuid'] = subnet_uuid if not updated: updated = True - if updated: - self._cassandra_db._cassandra_virtual_network_update(vn_uuid, vn_dict) - # end _update_subnet_uuid + if updated and do_update: + self._cassandra_db._cassandra_virtual_network_update(vn_uuid, + vn_dict) + # end update_subnet_uuid def _dbe_resync(self, obj_uuid, obj_cols): obj_type = None @@ -1315,7 +1321,7 @@ def _dbe_resync(self, obj_uuid, obj_cols): if (obj_type == 'virtual_network' and 'network_ipam_refs' in obj_dict): - self._update_subnet_uuid(obj_dict) + self._update_subnet_uuid(obj_dict, do_update=True) except Exception as e: self.config_object_error( obj_uuid, None, obj_type, 'dbe_resync:cassandra_read', str(e)) diff --git a/src/config/api-server/vnc_cfg_types.py b/src/config/api-server/vnc_cfg_types.py index 741ab636b79..56047ac523e 100644 --- a/src/config/api-server/vnc_cfg_types.py +++ b/src/config/api-server/vnc_cfg_types.py @@ -418,17 +418,6 @@ def _check_route_targets(cls, obj_dict, db_conn): return (True, '') # end _check_route_targets - @classmethod - def _check_and_create_subnet_uuid(cls, vn_dict): - ipam_refs = vn_dict.get('network_ipam_refs', []) - for ipam in ipam_refs: - vnsn = ipam['attr'] - subnets = vnsn['ipam_subnets'] - for subnet in subnets: - if not subnet.get('subnet_uuid'): - subnet['subnet_uuid'] = str(uuid.uuid4()) - # end _check_and_create_subnet_uuid - @classmethod def http_post_collection(cls, tenant_name, obj_dict, db_conn): try: @@ -450,7 +439,7 @@ def http_post_collection(cls, tenant_name, obj_dict, db_conn): if not ok: return (False, (403, pformat(obj_dict['fq_name']) + ' : ' + quota_limit)) - cls._check_and_create_subnet_uuid(obj_dict) + db_conn.update_subnet_uuid(obj_dict) (ok, error) = cls._check_route_targets(obj_dict, db_conn) if not ok: @@ -507,7 +496,7 @@ def http_put(cls, id, fq_name, obj_dict, db_conn): except Exception as e: return (False, (500, str(e))) - cls._check_and_create_subnet_uuid(obj_dict) + db_conn.update_subnet_uuid(obj_dict) (ok, error) = cls._check_route_targets(obj_dict, db_conn) if not ok: From 2662c484976f19b43aa0ab4a02351f49511ee64a Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 15 Oct 2014 15:37:31 -0700 Subject: [PATCH 025/218] bug 1381704 - update cassandra db with sequence when upgrading from earlier version Change-Id: Ic39a4e1fc46c5259f3a5de69e778ac1352dc034d --- src/discovery/disc_server.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/discovery/disc_server.py b/src/discovery/disc_server.py index 8ac8a8f985c..54dc4a9fa52 100644 --- a/src/discovery/disc_server.py +++ b/src/discovery/disc_server.py @@ -427,6 +427,10 @@ def api_publish(self, end_point = None): } self._db_conn.insert_service(service_type, sig, entry) + # handle upgrade + if 'sequence' not in entry: + entry['sequence'] = str(int(time.time())) + socket.gethostname() + entry['info'] = info entry['admin_state'] = 'up' entry['heartbeat'] = int(time.time()) From ebe89d65b04e5960aabe3d5835e98229bb2fd484 Mon Sep 17 00:00:00 2001 From: Sachin Bansal Date: Tue, 14 Oct 2014 14:22:08 -0700 Subject: [PATCH 026/218] Adding skeleton for a new daemon: prc-manager The name stands for 'physical router configuration manager'. It listens to rabbit-mq updates from API server. When messages are received, it reads corresponding information from cassandra. It manages configuration for physical routers (MX only for now) using netconf utility. Change-Id: I36ac5f8999f8f921f4ecec1bc87d4c7742ed88df --- src/config/prc-manager/MANIFEST.in | 2 + src/config/prc-manager/SConscript | 50 +++ .../prc-manager/contrail-prc-manager.conf | 6 + .../prc-manager/contrail-prc-manager.ini | 12 + .../contrail-prc-manager.initd.supervisord | 6 + .../prc-manager/prc_manager/__init__.py | 0 .../prc-manager/prc_manager/prc_manager.py | 317 ++++++++++++++++++ .../prc-manager/prcm_introspect.sandesh | 64 ++++ src/config/prc-manager/requirements.txt | 12 + src/config/prc-manager/run_tests.sh | 235 +++++++++++++ src/config/prc-manager/setup.py | 22 ++ src/config/prc-manager/test-requirements.txt | 18 + src/sandesh/common/vns.sandesh | 17 +- 13 files changed, 758 insertions(+), 3 deletions(-) create mode 100644 src/config/prc-manager/MANIFEST.in create mode 100644 src/config/prc-manager/SConscript create mode 100644 src/config/prc-manager/contrail-prc-manager.conf create mode 100644 src/config/prc-manager/contrail-prc-manager.ini create mode 100644 src/config/prc-manager/contrail-prc-manager.initd.supervisord create mode 100644 src/config/prc-manager/prc_manager/__init__.py create mode 100644 src/config/prc-manager/prc_manager/prc_manager.py create mode 100644 src/config/prc-manager/prcm_introspect.sandesh create mode 100644 src/config/prc-manager/requirements.txt create mode 100755 src/config/prc-manager/run_tests.sh create mode 100644 src/config/prc-manager/setup.py create mode 100644 src/config/prc-manager/test-requirements.txt diff --git a/src/config/prc-manager/MANIFEST.in b/src/config/prc-manager/MANIFEST.in new file mode 100644 index 00000000000..366665c4ede --- /dev/null +++ b/src/config/prc-manager/MANIFEST.in @@ -0,0 +1,2 @@ +recursive-include prc_manager/uve *.html *.xml *.css +recursive-include prc_manager/sandesh *.html *.xml *.css diff --git a/src/config/prc-manager/SConscript b/src/config/prc-manager/SConscript new file mode 100644 index 00000000000..4ff5acca772 --- /dev/null +++ b/src/config/prc-manager/SConscript @@ -0,0 +1,50 @@ +# -*- mode: python; -*- + +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# +Import('CfgmEnv') +env = CfgmEnv.Clone() + +setup_sources = ['setup.py', 'MANIFEST.in', ] + + +setup_sources_rules = [] +for file in setup_sources: + setup_sources_rules.append( + env.Install(Dir('.'), "#controller/src/config/prc-manager/" + file)) + +local_sources = ['prc_manager/__init__.py', 'iprc_manager/prc_manager.py', ] + +local_sources_rules = [] +for file in local_sources: + local_sources_rules.append( + env.Install("prc_manager", + "#controller/src/config/prc_manager/" + file)) + +prcm_introspect_pkg = env.SandeshGenPy('prcm_introspect.sandesh', + 'prc_manager/sandesh/', False) + +sdist_depends = [] +sdist_depends.extend(setup_sources_rules) +sdist_depends.extend(local_sources_rules) +sdist_depends.extend(prcm_introspect_pkg) +sdist_gen = env.Command('dist', 'setup.py', 'python setup.py sdist', chdir=1) + +env.Depends(sdist_gen, sdist_depends) +env.Default(sdist_gen) + +if 'install' in BUILD_TARGETS: + install_cmd = env.Command(None, 'setup.py', + 'python setup.py install %s' % + env['PYTHON_INSTALL_OPT'], + chdir=1) + env.Depends(install_cmd, sdist_depends) + env.Alias('install', install_cmd) + +env.Alias('install', env.Install(env['INSTALL_CONF'], + 'contrail-prc-manager.conf')) +env.Alias('install', env.InstallAs(env['INSTALL_INITD'] + + '/contrail-prc-manager', 'contrail-prc-manager.initd.supervisord')) +env.Alias('install', env.Install(env['INSTALL_CONF'] + + '/supervisord_config_files', 'contrail-prc-manager.ini')) diff --git a/src/config/prc-manager/contrail-prc-manager.conf b/src/config/prc-manager/contrail-prc-manager.conf new file mode 100644 index 00000000000..dd6bcf90702 --- /dev/null +++ b/src/config/prc-manager/contrail-prc-manager.conf @@ -0,0 +1,6 @@ +[DEFAULTS] +log_file = /var/log/contrail/contrail-prc-manager.log +log_local = 1 +log_level = SYS_NOTICE +disc_server_ip = 127.0.0.1 +disc_server_port = 5998 diff --git a/src/config/prc-manager/contrail-prc-manager.ini b/src/config/prc-manager/contrail-prc-manager.ini new file mode 100644 index 00000000000..4293017cca3 --- /dev/null +++ b/src/config/prc-manager/contrail-prc-manager.ini @@ -0,0 +1,12 @@ +[program:contrail-prc-manager] +command=/usr/bin/contrail-prc-manager --conf_file /etc/contrail/prc_manager.conf +priority=450 +autostart=true +autorestart=true +killasgroup=true +stopsignal=KILL +redirect_stderr=true +stdout_logfile=/var/log/contrail/contrail-prc-manager-stdout.log +stderr_logfile=/dev/null +exitcodes=0 ; 'expected' exit codes for process (default 0,2) +user=contrail diff --git a/src/config/prc-manager/contrail-prc-manager.initd.supervisord b/src/config/prc-manager/contrail-prc-manager.initd.supervisord new file mode 100644 index 00000000000..2156c6d090c --- /dev/null +++ b/src/config/prc-manager/contrail-prc-manager.initd.supervisord @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# chkconfig: 2345 99 01 +# description: Juniper Network Virtualization Schema Transformer + +supervisorctl -s unix:///tmp/supervisord_config.sock ${1} `basename ${0}` diff --git a/src/config/prc-manager/prc_manager/__init__.py b/src/config/prc-manager/prc_manager/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/config/prc-manager/prc_manager/prc_manager.py b/src/config/prc-manager/prc_manager/prc_manager.py new file mode 100644 index 00000000000..9d70a635978 --- /dev/null +++ b/src/config/prc-manager/prc_manager/prc_manager.py @@ -0,0 +1,317 @@ +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# + +""" +This file contains implementation of managing physical router configuration +""" + +from cfgm_common.vnc_cassandra import VncCassandraClient +from cfgm_common.vnc_kombu import VncKombuClient +import cgitb + +from pysandesh.sandesh_base import * +from pysandesh.sandesh_logger import * +from pysandesh.gen_py.sandesh.ttypes import SandeshLevel +from cfgm_common.uve.virtual_network.ttypes import * +from sandesh_common.vns.ttypes import Module, NodeType +from sandesh_common.vns.constants import ModuleNames, Module2NodeType, \ + NodeTypeNames, INSTANCE_ID_DEFAULT +import discoveryclient.client as client + + +class PrcManager(object): + def __init__(self, args=None): + self._args = args + + # Initialize discovery client + self._disc = None + if self._args.disc_server_ip and self._args.disc_server_port: + self._disc = client.DiscoveryClient( + self._args.disc_server_ip, + self._args.disc_server_port, + ModuleNames[Module.PRC_MANAGER]) + + self._sandesh = Sandesh() + module = Module.PRC_MANAGER + module_name = ModuleNames[module] + node_type = Module2NodeType[module] + node_type_name = NodeTypeNames[node_type] + instance_id = INSTANCE_ID_DEFAULT + hostname = socket.gethostname() + _sandesh.init_generator( + module_name, hostname, node_type_name, instance_id, + self._args.collectors, 'to_bgp_context', + int(args.http_server_port), + ['cfgm_common', 'prc_manager.sandesh'], self._disc) + _sandesh.set_logging_params(enable_local_log=args.log_local, + category=args.log_category, + level=args.log_level, + file=args.log_file, + enable_syslog=args.use_syslog, + syslog_facility=args.syslog_facility) + ConnectionState.init( + _sandesh, hostname, module_name, instance_id, + staticmethod(ConnectionState.get_process_state_cb), + NodeStatusUVE, NodeStatus) + + rabbit_server = self._args.rabbit_server + rabbit_port = self._args.rabbit_port + rabbit_user = self._args.rabbit_user + rabbit_password = self._args.rabbit_password + rabbit_vhost = self._args.rabbit_vhost + + q_name = 'prc_manager.%s' % (socket.gethostname()) + self._vnc_kombu = VncKombuClient(rabbit_server, rabbit_port, + rabbit_user, rabbit_password, + rabbit_vhost, q_name, + self._vnc_subscribe_callback, + self.config_log) + + cass_server_list = self._args.cassandra_server_list + reset_config = self._args.reset_config + self._cassandra = VncCassandraClient(cass_server_list, reset_config, + self._args.cluster_id, None, + self.config_log) + self._vnc_kombu.connect(delete_old_q=True) + # end __init__ + + def config_log(self, msg, level): + self._sandesh.logger().log(SandeshLogger.get_py_logger_level(level), + msg) + + def _vnc_subscribe_callback(self, oper_info): + try: + msg = "Notification Message: %s" % (pformat(oper_info)) + self.config_log(msg, level=SandeshLevel.SYS_DEBUG) + + if oper_info['oper'] == 'CREATE': + self._dbe_create_notification(oper_info) + if oper_info['oper'] == 'UPDATE': + self._dbe_update_notification(oper_info) + elif oper_info['oper'] == 'DELETE': + self._dbe_delete_notification(oper_info) + + except Exception: + string_buf = cStringIO.StringIO() + cgitb.Hook(file=string_buf, format="text").handle(sys.exc_info()) + self.config_log(string_buf.getvalue(), + level=SandeshLevel.SYS_ERR) + # end _vnc_subscribe_callback + + +def parse_args(args_str): + ''' + Eg. python prc_manager.py --rabbit_server localhost + -- rabbit_port 5672 + -- rabbit_user guest + -- rabbit_password guest + --cassandra_server_list 10.1.2.3:9160 + --api_server_ip 10.1.2.3 + --api_server_port 8082 + --zk_server_ip 10.1.2.3 + --zk_server_port 2181 + --collectors 127.0.0.1:8086 + --disc_server_ip 127.0.0.1 + --disc_server_port 5998 + --http_server_port 8090 + --log_local + --log_level SYS_DEBUG + --log_category test + --log_file + --use_syslog + --syslog_facility LOG_USER + --cluster_id + [--reset_config] + ''' + + # Source any specified config/ini file + # Turn off help, so we all options in response to -h + conf_parser = argparse.ArgumentParser(add_help=False) + + conf_parser.add_argument("-c", "--conf_file", action='append', + help="Specify config file", metavar="FILE") + args, remaining_argv = conf_parser.parse_known_args(args_str.split()) + + defaults = { + 'rabbit_server': 'localhost', + 'rabbit_port': '5672', + 'rabbit_user': 'guest', + 'rabbit_password': 'guest', + 'rabbit_vhost': None, + 'cassandra_server_list': '127.0.0.1:9160', + 'api_server_ip': '127.0.0.1', + 'api_server_port': '8082', + 'zk_server_ip': '127.0.0.1', + 'zk_server_port': '2181', + 'collectors': None, + 'disc_server_ip': None, + 'disc_server_port': None, + 'http_server_port': '8087', + 'log_local': False, + 'log_level': SandeshLevel.SYS_DEBUG, + 'log_category': '', + 'log_file': Sandesh._DEFAULT_LOG_FILE, + 'use_syslog': False, + 'syslog_facility': Sandesh._DEFAULT_SYSLOG_FACILITY, + 'cluster_id': '', + } + secopts = { + 'use_certs': False, + 'keyfile': '', + 'certfile': '', + 'ca_certs': '', + 'ifmap_certauth_port': "8444", + } + ksopts = { + 'admin_user': 'user1', + 'admin_password': 'password1', + 'admin_tenant_name': 'default-domain' + } + + if args.conf_file: + config = ConfigParser.SafeConfigParser() + config.read(args.conf_file) + defaults.update(dict(config.items("DEFAULTS"))) + if ('SECURITY' in config.sections() and + 'use_certs' in config.options('SECURITY')): + if config.getboolean('SECURITY', 'use_certs'): + secopts.update(dict(config.items("SECURITY"))) + if 'KEYSTONE' in config.sections(): + ksopts.update(dict(config.items("KEYSTONE"))) + + # Override with CLI options + # Don't surpress add_help here so it will handle -h + parser = argparse.ArgumentParser( + # Inherit options from config_parser + parents=[conf_parser], + # print script description with -h/--help + description=__doc__, + # Don't mess with format of description + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + defaults.update(secopts) + defaults.update(ksopts) + parser.set_defaults(**defaults) + + parser.add_argument( + "--ifmap_server_ip", help="IP address of ifmap server") + parser.add_argument("--ifmap_server_port", help="Port of ifmap server") + + # TODO should be from certificate + parser.add_argument("--ifmap_username", + help="Username known to ifmap server") + parser.add_argument("--ifmap_password", + help="Password known to ifmap server") + parser.add_argument( + "--cassandra_server_list", + help="List of cassandra servers in IP Address:Port format", + nargs='+') + parser.add_argument( + "--reset_config", action="store_true", + help="Warning! Destroy previous configuration and start clean") + parser.add_argument("--api_server_ip", + help="IP address of API server") + parser.add_argument("--api_server_port", + help="Port of API server") + parser.add_argument("--zk_server_ip", + help="IP address:port of zookeeper server") + parser.add_argument("--collectors", + help="List of VNC collectors in ip:port format", + nargs="+") + parser.add_argument("--disc_server_ip", + help="IP address of the discovery server") + parser.add_argument("--disc_server_port", + help="Port of the discovery server") + parser.add_argument("--http_server_port", + help="Port of local HTTP server") + parser.add_argument("--log_local", action="store_true", + help="Enable local logging of sandesh messages") + parser.add_argument( + "--log_level", + help="Severity level for local logging of sandesh messages") + parser.add_argument( + "--log_category", + help="Category filter for local logging of sandesh messages") + parser.add_argument("--log_file", + help="Filename for the logs to be written to") + parser.add_argument("--use_syslog", action="store_true", + help="Use syslog for logging") + parser.add_argument("--syslog_facility", + help="Syslog facility to receive log lines") + parser.add_argument("--admin_user", + help="Name of keystone admin user") + parser.add_argument("--admin_password", + help="Password of keystone admin user") + parser.add_argument("--admin_tenant_name", + help="Tenant name for keystone admin user") + parser.add_argument("--cluster_id", + help="Used for database keyspace separation") + args = parser.parse_args(remaining_argv) + if type(args.cassandra_server_list) is str: + args.cassandra_server_list = args.cassandra_server_list.split() + if type(args.collectors) is str: + args.collectors = args.collectors.split() + + return args +# end parse_args + + +def main(args_str=None): + global _zookeeper_client + if not args_str: + args_str = ' '.join(sys.argv[1:]) + args = parse_args(args_str) + if args.cluster_id: + client_pfx = args.cluster_id + '-' + zk_path_pfx = args.cluster_id + '/' + else: + client_pfx = '' + zk_path_pfx = '' + _zookeeper_client = ZookeeperClient(client_pfx+"prc-manager", + args.zk_server_ip) + _zookeeper_client.master_election(zk_path_pfx+"/prc-manager", + os.getpid(), run_prc_manager, + args) +# end main + + +def run_prc_manager(args): + global _vnc_lib + + def connection_state_update(status, message=None): + ConnectionState.update( + conn_type=ConnectionType.APISERVER, name='ApiServer', + status=status, message=message or '', + server_addrs=['%s:%s' % (args.api_server_ip, + args.api_server_port)]) + # end connection_state_update + + # Retry till API server is up + connected = False + connection_state_update(ConnectionStatus.INIT) + while not connected: + try: + _vnc_lib = VncApi( + args.admin_user, args.admin_password, args.admin_tenant_name, + args.api_server_ip, args.api_server_port) + connected = True + connection_state_update(ConnectionStatus.UP) + except requests.exceptions.ConnectionError as e: + # Update connection info + connection_state_update(ConnectionStatus.DOWN, str(e)) + time.sleep(3) + except ResourceExhaustionError: # haproxy throws 503 + time.sleep(3) + + prc_manager = PrcManager(args) +# end run_prc_manager + + +def server_main(): + cgitb.enable(format='text') + main() +# end server_main + +if __name__ == '__main__': + server_main() diff --git a/src/config/prc-manager/prcm_introspect.sandesh b/src/config/prc-manager/prcm_introspect.sandesh new file mode 100644 index 00000000000..6d136cc8fc1 --- /dev/null +++ b/src/config/prc-manager/prcm_introspect.sandesh @@ -0,0 +1,64 @@ +// +// prcm_introspect.sandesh +// +// Introspect structs for Schema Transformer +// +// Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +// + +struct Acl { + 1: string name; + 2: bool dynamic_acl; +} + +struct VirtualNetwork { + 1: string name; + 2: list policies; + 3: list connections; + 4: list routing_instances; + 5: string acl; + 6: string dynamic_acl; +} + +request sandesh VnList { + 1: string vn_name; +} + +response sandesh VnListResp { + 1: list vn_names; +} + +struct RoutingInstance { + 1: string name; + 2: string service_chain; + 3: list connections; +} + +response sandesh RoutingInstanceListResp { + 1: list routing_instances; +} + +request sandesh RoutintInstanceList { + 1: string vn_name; + 2: string ri_name; +} + +struct ServiceChain { + 1: string sc_name; + 2: string left_virtual_network; + 3: string right_virtual_network; + 4: string direction; + 5: string src_ports; + 6: string dst_ports; + 7: list service_list; + 9: string protocol; + 10: bool created; +} + +response sandesh ServiceChainListResp { + 1: list service_chains; +} + +request sandesh ServiceChainList { + 1: string sc_name; +} diff --git a/src/config/prc-manager/requirements.txt b/src/config/prc-manager/requirements.txt new file mode 100644 index 00000000000..dd3206962cb --- /dev/null +++ b/src/config/prc-manager/requirements.txt @@ -0,0 +1,12 @@ +lxml>=2.3.3 +gevent +geventhttpclient==1.0a +pycassa>=1.7.2 +netaddr>=0.7.5 +bitarray>=0.8.0 +psutil>=0.4.1 +python-novaclient +kombu +netifaces +bottle +stevedore diff --git a/src/config/prc-manager/run_tests.sh b/src/config/prc-manager/run_tests.sh new file mode 100755 index 00000000000..843114f18bb --- /dev/null +++ b/src/config/prc-manager/run_tests.sh @@ -0,0 +1,235 @@ +#!/bin/bash +set -eu + +function usage { + echo "Usage: $0 [OPTION]..." + echo "Run Contrail's test suite(s)" + echo "" + echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" + echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" + echo " -s, --no-site-packages Isolate the virtualenv from the global Python environment" + echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." + echo " -u, --update Update the virtual environment with any newer package versions" + echo " -p, --pep8 Just run PEP8 and HACKING compliance check" + echo " -P, --no-pep8 Don't run static code checks" + echo " -c, --coverage Generate coverage report" + echo " -d, --debug Run tests with testtools instead of testr. This allows you to use the debugger." + echo " -h, --help Print this usage message" + echo " --hide-elapsed Don't print the elapsed time for each test along with slow test list" + echo " --virtual-env-path Location of the virtualenv directory" + echo " Default: \$(pwd)" + echo " --virtual-env-name Name of the virtualenv directory" + echo " Default: .venv" + echo " --tools-path Location of the tools directory" + echo " Default: \$(pwd)" + echo " --concurrency How many processes to use when running the tests. A value of 0 autodetects concurrency from your CPU count" + echo " Default: 0" + echo "" + echo "Note: with no options specified, the script will try to run the tests in a virtual environment," + echo " If no virtualenv is found, the script will ask if you would like to create one. If you " + echo " prefer to run tests NOT in a virtual environment, simply pass the -N option." + exit +} + +function process_options { + i=1 + while [ $i -le $# ]; do + case "${!i}" in + -h|--help) usage;; + -V|--virtual-env) always_venv=1; never_venv=0;; + -N|--no-virtual-env) always_venv=0; never_venv=1;; + -s|--no-site-packages) no_site_packages=1;; + -f|--force) force=1;; + -u|--update) update=1;; + -p|--pep8) just_pep8=1;; + -P|--no-pep8) no_pep8=1;; + -c|--coverage) coverage=1;; + -d|--debug) debug=1;; + --virtual-env-path) + (( i++ )) + venv_path=${!i} + ;; + --virtual-env-name) + (( i++ )) + venv_dir=${!i} + ;; + --tools-path) + (( i++ )) + tools_path=${!i} + ;; + --concurrency) + (( i++ )) + concurrency=${!i} + ;; + -*) testropts="$testropts ${!i}";; + *) testrargs="$testrargs ${!i}" + esac + (( i++ )) + done +} + +tools_path=${tools_path:-$(pwd)/../common/tests/} +root_path=${root_path:-$(pwd)} +venv_path=${venv_path:-$(pwd)} +venv_dir=${venv_name:-.venv} +with_venv=${tools_path}/tools/with_venv.sh +always_venv=0 +never_venv=0 +force=0 +no_site_packages=0 +installvenvopts= +testrargs= +testropts= +wrapper="" +just_pep8=0 +no_pep8=0 +coverage=0 +debug=0 +update=0 +concurrency=0 + +LANG=en_US.UTF-8 +LANGUAGE=en_US:en +LC_ALL=C + +process_options $@ +# Make our paths available to other scripts we call +export venv_path +export venv_dir +export venv_name +export tools_dir +export venv=${venv_path}/${venv_dir} + +if [ $no_site_packages -eq 1 ]; then + installvenvopts="--no-site-packages" +fi + +function run_tests { + # Cleanup *pyc + ${wrapper} find . -type f -name "*.pyc" -delete + + if [ $debug -eq 1 ]; then + if [ "$testropts" = "" ] && [ "$testrargs" = "" ]; then + # Default to running all tests if specific test is not + # provided. + testrargs="discover ./tests" + fi + ${wrapper} python -m testtools.run $testropts $testrargs + + # Short circuit because all of the testr and coverage stuff + # below does not make sense when running testtools.run for + # debugging purposes. + return $? + fi + + if [ $coverage -eq 1 ]; then + TESTRTESTS="$TESTRTESTS --coverage" + else + TESTRTESTS="$TESTRTESTS" + fi + + # Just run the test suites in current environment + set +e + testrargs=`echo "$testrargs" | sed -e's/^\s*\(.*\)\s*$/\1/'` + TESTRTESTS="$TESTRTESTS --testr-args='--subunit --concurrency $concurrency $testropts $testrargs'" + if [ setup.cfg -nt nova.egg-info/entry_points.txt ] + then + ${wrapper} python setup.py egg_info + fi + echo "Running \`${wrapper} $TESTRTESTS\`" + if ${wrapper} which subunit-2to1 2>&1 > /dev/null + then + # subunit-2to1 is present, testr subunit stream should be in version 2 + # format. Convert to version one before colorizing. + bash -c "${wrapper} $TESTRTESTS | ${wrapper} subunit-2to1 | ${wrapper} ${tools_path}/tools/colorizer.py" + else + bash -c "${wrapper} $TESTRTESTS | ${wrapper} ${tools_path}/tools/colorizer.py" + fi + RESULT=$? + set -e + + copy_subunit_log + + if [ $coverage -eq 1 ]; then + echo "Generating coverage report in covhtml/" + # Don't compute coverage for common code, which is tested elsewhere + ${wrapper} coverage combine + ${wrapper} coverage html --include='nova/*' --omit='nova/openstack/common/*' -d covhtml -i + fi + + return $RESULT +} + +function copy_subunit_log { + LOGNAME=`cat .testrepository/next-stream` + LOGNAME=$(($LOGNAME - 1)) + LOGNAME=".testrepository/${LOGNAME}" + cp $LOGNAME subunit.log +} + +function run_pep8 { + #HACK + return 0 + + echo "Running flake8 ..." + if [ $never_venv -eq 1 ]; then + echo "**WARNING**:" + echo "Running flake8 without virtual env may miss OpenStack HACKING detection" + fi + bash -c "${wrapper} flake8" +} + + +TESTRTESTS="python setup.py testr" + +if [ $never_venv -eq 0 ] +then + # Remove the virtual environment if --force used + if [ $force -eq 1 ]; then + echo "Cleaning virtualenv..." + rm -rf ${venv} + fi + if [ $update -eq 1 ]; then + echo "Updating virtualenv..." + env tools_path=${tools_path} root_path=${root_path} python ../common/tests/tools/install_venv.py $installvenvopts + fi + if [ -e ${venv} ]; then + wrapper="${with_venv}" + else + if [ $always_venv -eq 1 ]; then + # Automatically install the virtualenv + env tools_path=${tools_path} root_path=${root_path} python ../common/tests/tools/install_venv.py $installvenvopts + wrapper="${with_venv}" + else + echo -e "No virtual environment found...create one? (Y/n) \c" + read use_ve + if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then + # Install the virtualenv and run the test suite in it + env tools_path=${tools_path} root_path=${root_path} python ../common/tests/tools/install_venv.py $installvenvopts + wrapper=${with_venv} + fi + fi + fi +fi + +# Delete old coverage data from previous runs +if [ $coverage -eq 1 ]; then + ${wrapper} coverage erase +fi + +if [ $just_pep8 -eq 1 ]; then + run_pep8 + exit +fi + +run_tests + +# NOTE(sirp): we only want to run pep8 when we're running the full-test suite, +# not when we're running tests individually. To handle this, we need to +# distinguish between options (testropts), which begin with a '-', and +# arguments (testrargs). +if [ -z "$testrargs" ]; then + if [ $no_pep8 -eq 0 ]; then + run_pep8 + fi +fi diff --git a/src/config/prc-manager/setup.py b/src/config/prc-manager/setup.py new file mode 100644 index 00000000000..6adda3d9c96 --- /dev/null +++ b/src/config/prc-manager/setup.py @@ -0,0 +1,22 @@ +# +# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. +# +from setuptools import setup + +setup( + name='prc_manager', + version='0.1dev', + packages=['prc_manager', + 'prc_manager.sandesh', + 'prc_manager.sandesh.prc_introspect', + ], + package_data={'': ['*.html', '*.css', '*.xml']}, + zip_safe=False, + long_description="VNC Configuration Physical Router Configuration Manager", + entry_points = { + # Please update sandesh/common/vns.sandesh on process name change + 'console_scripts' : [ + 'contrail-prc-manager = prc_manager.prc_manager:server_main', + ], + }, +) diff --git a/src/config/prc-manager/test-requirements.txt b/src/config/prc-manager/test-requirements.txt new file mode 100644 index 00000000000..af63ec69af3 --- /dev/null +++ b/src/config/prc-manager/test-requirements.txt @@ -0,0 +1,18 @@ +python-subunit +testrepository +flexmock +coverage +pyaml +python-keystoneclient +webtest +kazoo +ncclient +jsonpickle +../../../../third_party/ifmap-python-client +../../../../build/production/config/common/dist/cfgm_common-0.1dev.tar.gz +../../../../build/production/api-lib/dist/vnc_api-0.1dev.tar.gz +../../../../build/production/discovery/client/dist/discoveryclient-0.1dev.tar.gz +../../../../build/production/tools/sandesh/library/python/dist/sandesh-0.1dev.tar.gz +../../../../build/production/sandesh/common/dist/sandesh-common-0.1dev.tar.gz +../../../../build/production/config/api-server/dist/vnc_cfg_api_server-0.1dev.tar.gz +../../../../build/noarch/config/svc-monitor diff --git a/src/sandesh/common/vns.sandesh b/src/sandesh/common/vns.sandesh index 842605a83b5..1cab0f64d09 100644 --- a/src/sandesh/common/vns.sandesh +++ b/src/sandesh/common/vns.sandesh @@ -15,6 +15,7 @@ const string SERVICE_DNSD = "contrail-dns" const string SERVICE_API_SERVER = "contrail-api:0" const string SERVICE_SCHEMA_TRANSFORMER = "contrail-schema" const string SERVICE_SVC_MONITOR = "contrail-svc-monitor" +const string SERVICE_PRC_MANAGER = "contrail-prc-manager" const string SERVICE_COLLECTOR = "contrail-collector" const string SERVICE_QUERY_ENGINE = "contrail-query-engine" const string SERVICE_OPSERVER = "contrail-analytics-api" @@ -49,6 +50,7 @@ const u16 HttpPortApiServer = 8084 const u16 HttpPortAgent = 8085 const u16 HttpPortSchemaTransformer = 8087 const u16 HttpPortSvcMonitor = 8088 +const u16 HttpPortPrcManager = 8096 const u16 HttpPortCollector = 8089 const u16 HttpPortOpserver = 8090 const u16 HttpPortQueryEngine = 8091 @@ -91,6 +93,7 @@ const map ServiceHttpPortMap = { SERVICE_API_SERVER : HttpPortApiServer, SERVICE_SCHEMA_TRANSFORMER : HttpPortSchemaTransformer, SERVICE_SVC_MONITOR : HttpPortSvcMonitor, + SERVICE_PRC_MANAGER : HttpPortPrcManager, SERVICE_CONFIG_NODE_MGR : HttpPortConfigNodemgr, SERVICE_ANALYTICS_NODE_MGR : HttpPortAnalyticsNodemgr, SERVICE_COMPUTE_NODE_MGR : HttpPortVRouterNodemgr, @@ -108,6 +111,7 @@ const list NodeUVEImplementedServices = [ SERVICE_API_SERVER, SERVICE_SCHEMA_TRANSFORMER, SERVICE_SVC_MONITOR, + SERVICE_PRC_MANAGER, ] enum Module { @@ -119,6 +123,7 @@ enum Module { COLLECTOR, QUERY_ENGINE, SVC_MONITOR, + PRC_MANAGER, DNS, DISCOVERY_SERVICE, IFMAP_SERVER, @@ -141,6 +146,7 @@ const string MODULE_OPSERVER_NAME = "OpServer" const string MODULE_COLLECTOR_NAME = "Collector" const string MODULE_QUERY_ENGINE_NAME = "QueryEngine" const string MODULE_SVC_MONITOR_NAME = "ServiceMonitor" +const string MODULE_PRC_MANAGER_NAME = "PrcManager" const string MODULE_DNS_NAME = "DnsAgent" const string MODULE_DISCOVERY_SERVICE_NAME = "DiscoveryService" const string MODULE_IFMAP_SERVER_NAME = "IfmapServer" @@ -162,6 +168,7 @@ const map ModuleNames = { Module.COLLECTOR : MODULE_COLLECTOR_NAME, Module.QUERY_ENGINE : MODULE_QUERY_ENGINE_NAME, Module.SVC_MONITOR : MODULE_SVC_MONITOR_NAME, + Module.PRC_MANAGER : MODULE_PRC_MANAGER_NAME, Module.DNS : MODULE_DNS_NAME, Module.DISCOVERY_SERVICE : MODULE_DISCOVERY_SERVICE_NAME, Module.IFMAP_SERVER : MODULE_IFMAP_SERVER_NAME, @@ -184,6 +191,7 @@ const map ModuleIds = { MODULE_COLLECTOR_NAME : Module.COLLECTOR, MODULE_QUERY_ENGINE_NAME : Module.QUERY_ENGINE, MODULE_SVC_MONITOR_NAME : Module.SVC_MONITOR, + MODULE_PRC_MANAGER_NAME : Module.PRC_MANAGER, MODULE_DNS_NAME : Module.DNS, MODULE_DISCOVERY_SERVICE_NAME : Module.DISCOVERY_SERVICE MODULE_IFMAP_SERVER_NAME : Module.IFMAP_SERVER, @@ -229,6 +237,7 @@ const map Module2NodeType = { Module.COLLECTOR : NodeType.ANALYTICS, Module.QUERY_ENGINE : NodeType.ANALYTICS, Module.SVC_MONITOR : NodeType.CONFIG, + Module.PRC_MANAGER : NodeType.CONFIG, Module.DNS : NodeType.CONTROL, Module.DISCOVERY_SERVICE : NodeType.CONFIG, Module.IFMAP_SERVER : NodeType.CONFIG, @@ -315,11 +324,13 @@ const map> ModuleCategoryMap = { Module.QUERY_ENGINE : [Category.DEFAULT, ], Module.SVC_MONITOR : [Category.DEFAULT, - ], + ], + Module.PRC_MANAGER : [Category.DEFAULT, + ], Module.DNS : [Category.DEFAULT, Category.DNSAGENT, - ], + ], Module.DISCOVERY_SERVICE : [Category.DEFAULT, Category.DISCOVERY, - ], + ], } From 2ab18d7a948302aa54c8abfc7025cda48844871c Mon Sep 17 00:00:00 2001 From: Sachin Bansal Date: Wed, 15 Oct 2014 16:00:18 -0700 Subject: [PATCH 027/218] Catch PermissionDenied exception on security_group_update so that we can return proper error when sg rule quota is exceeded. Change-Id: I1ebfe45a50521653ec92f115e12b692cc554dec4 Closes-Bug: 1365463 --- src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index d9438653b25..dc80c21373c 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -237,7 +237,11 @@ def _security_group_rule_create(self, sg_id, sg_rule): rules.add_policy_rule(sg_rule) sg_vnc.set_security_group_entries(rules) - self._vnc_lib.security_group_update(sg_vnc) + try: + self._vnc_lib.security_group_update(sg_vnc) + except PermissionDenied as e: + self._raise_contrail_exception('BadRequest', + resource='security_group_rule', msg=str(e)) return #end _security_group_rule_create From 81ab4cf4360557f39b09a499e881db50d6b249db Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Wed, 15 Oct 2014 13:52:21 -0700 Subject: [PATCH 028/218] Fix circular route re-origination bug with transit VN Problem: When a service is applied between a VN and a transit VN, routes from the VN that are re-originated into the transit VN as ServiceChain routes get re-originated again as ServiceChain routes into the regular VN. Cause: Implementation prior to transit VN used to ignore routes that did belong to the destination VN of the service chain. Code changes for transit VN functionality relaxed this check, but did not cover the case where route belongs to the source VN. Fix: Add check to ignore routes from source VN. Change-Id: Ifdff8e828f0d4a9bc20ab055e0e9206d2cfd347a Partial-Bug: 1365277 --- src/bgp/routing-instance/service_chaining.cc | 3 + src/bgp/test/bgp_test_util.cc | 38 +- src/bgp/test/bgp_test_util.h | 6 +- .../svc_static_route_intergration_test.cc | 991 +++++++++++------- src/bgp/testdata/service_chain_6.xml | 7 + 5 files changed, 664 insertions(+), 381 deletions(-) create mode 100644 src/bgp/testdata/service_chain_6.xml diff --git a/src/bgp/routing-instance/service_chaining.cc b/src/bgp/routing-instance/service_chaining.cc index 900b7d6b16c..fb126518fd8 100644 --- a/src/bgp/routing-instance/service_chaining.cc +++ b/src/bgp/routing-instance/service_chaining.cc @@ -132,8 +132,11 @@ bool ServiceChain::Match(BgpServer *server, BgpTable *table, deleted = true; int vn_index = GetOriginVnIndex(route); + int src_vn_index = src_->virtual_network_index(); int dest_vn_index = dest_->virtual_network_index(); if (!vn_index || dest_vn_index != vn_index) { + if (src_vn_index == vn_index) + deleted = true; if (!dest_->virtual_network_allow_transit()) deleted = true; if (!dest_vn_index) diff --git a/src/bgp/test/bgp_test_util.cc b/src/bgp/test/bgp_test_util.cc index 53f4e425d5a..eab9f8160cd 100644 --- a/src/bgp/test/bgp_test_util.cc +++ b/src/bgp/test/bgp_test_util.cc @@ -4,6 +4,7 @@ #include "bgp/test/bgp_test_util.h" +#include #include #include @@ -15,7 +16,12 @@ using namespace std; namespace bgp_util { string NetworkConfigGenerate( const vector &instance_names, - const multimap &connections) { + const multimap &connections, + const vector &networks, + const vector &network_ids) { + assert(networks.empty() || instance_names.size() == networks.size()); + assert(networks.size() == network_ids.size()); + int index; xml_document xdoc; xml_node env = xdoc.append_child("Envelope"); @@ -28,14 +34,25 @@ string NetworkConfigGenerate( xml_node item = update.append_child("resultItem"); xml_node id = item.append_child("identity"); string vn("virtual-network:"); - vn.append(*iter); + if (networks.empty()) { + vn.append(*iter); + } else { + vn.append(networks[index]); + } id.append_attribute("name") = vn.c_str(); xml_node meta = item.append_child("metadata"); xml_node vn_properties = meta.append_child("virtual-network-properties"); xml_node net_id = vn_properties.append_child("network-id"); - char value[16]; - snprintf(value, sizeof(value), "%d", ++index); - net_id.append_child(node_pcdata).set_value(value); + int value; + if (network_ids.empty()) { + value = index + 1; + } else { + value = network_ids[index]; + } + char value_str[16]; + snprintf(value_str, sizeof(value), "%d", value); + net_id.append_child(node_pcdata).set_value(value_str); + index++; } index = 0; for (vector::const_iterator iter = instance_names.begin(); @@ -47,17 +64,23 @@ string NetworkConfigGenerate( id1.append_attribute("name") = instance.c_str(); xml_node id2 = item.append_child("identity"); ostringstream target; - target << "route-target:target:64496:" << ++index; + target << "route-target:target:64496:" << (index + 1); id2.append_attribute("name") = target.str().c_str(); xml_node meta = item.append_child("metadata"); meta.append_child("instance-target"); + index++; } + index = 0; for (vector::const_iterator iter = instance_names.begin(); iter != instance_names.end(); ++iter) { xml_node item = update.append_child("resultItem"); xml_node id1 = item.append_child("identity"); string vn("virtual-network:"); - vn.append(*iter); + if (networks.empty()) { + vn.append(*iter); + } else { + vn.append(networks[index]); + } id1.append_attribute("name") = vn.c_str(); xml_node id2 = item.append_child("identity"); string instance("routing-instance:"); @@ -65,6 +88,7 @@ string NetworkConfigGenerate( id2.append_attribute("name") = instance.c_str(); xml_node meta = item.append_child("metadata"); meta.append_child("virtual-network-routing-instance"); + index++; } for (multimap::const_iterator iter = connections.begin(); iter != connections.end(); ++iter) { diff --git a/src/bgp/test/bgp_test_util.h b/src/bgp/test/bgp_test_util.h index 501b7637eec..7949c497eb9 100644 --- a/src/bgp/test/bgp_test_util.h +++ b/src/bgp/test/bgp_test_util.h @@ -11,8 +11,10 @@ namespace bgp_util { std::string NetworkConfigGenerate( - const std::vector &instance_names, - const std::multimap &connections); + const std::vector &instance_names, + const std::multimap &connections, + const std::vector &networks = std::vector(), + const std::vector &network_ids = std::vector()); } #endif diff --git a/src/bgp/test/svc_static_route_intergration_test.cc b/src/bgp/test/svc_static_route_intergration_test.cc index d6b8ac55d1a..518d229baf7 100644 --- a/src/bgp/test/svc_static_route_intergration_test.cc +++ b/src/bgp/test/svc_static_route_intergration_test.cc @@ -161,7 +161,8 @@ class ServiceChainTest : public ::testing::Test { : thread_(&evm_), cn1_xmpp_server_(NULL), cn2_xmpp_server_(NULL), - connected_table_(NULL), + connected_table_("blue"), + transparent_(false), aggregate_enable_(false), mx_push_connected_(false), single_si_(true), @@ -363,19 +364,25 @@ class ServiceChainTest : public ::testing::Test { void ConfigureInstancesAndConnections() { vector instance_names; multimap connections; + vector networks; + vector network_ids; if (single_si_) { instance_names = list_of ("blue")("blue-i1")("red-i2")("red")("purple"); + networks = list_of("blue")("blue")("red")("red")("purple"); + network_ids = list_of(1)(1)(2)(2)(3); connections = map_list_of ("blue","blue-i1")("red-i2","red")("red","purple"); } else { instance_names = list_of ("blue")("blue-i1")("red-i2")("blue-i3")("red-i4")("red"); + networks = list_of("blue")("blue")("red")("blue")("red")("red"); + network_ids = list_of(1)(1)(2)(1)(2)(2); connections = map_list_of ("blue","blue-i1")("red-i2","blue-i3")("red-i4","red"); } - NetworkConfig(instance_names, connections); + NetworkConfig(instance_names, connections, networks, network_ids); VerifyNetworkConfig(cn1_.get(), instance_names); VerifyNetworkConfig(cn2_.get(), instance_names); @@ -385,11 +392,22 @@ class ServiceChainTest : public ::testing::Test { GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); SetServiceChainProperty(cn1_.get(), "blue-i1", params); task_util::WaitForIdle(); + params = GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); SetServiceChainProperty(cn2_.get(), "blue-i1", params); task_util::WaitForIdle(); + params = + GetChainConfig("controller/src/bgp/testdata/service_chain_6.xml"); + SetServiceChainProperty(cn1_.get(), "red-i2", params); + task_util::WaitForIdle(); + + params = + GetChainConfig("controller/src/bgp/testdata/service_chain_6.xml"); + SetServiceChainProperty(cn2_.get(), "red-i2", params); + task_util::WaitForIdle(); + if (single_si_) return; @@ -404,9 +422,11 @@ class ServiceChainTest : public ::testing::Test { } void NetworkConfig(const vector &instance_names, - const multimap &connections) { - string netconf( - bgp_util::NetworkConfigGenerate(instance_names, connections)); + const multimap &connections, + const vector &networks, + const vector &network_ids) { + string netconf(bgp_util::NetworkConfigGenerate( + instance_names, connections, networks, network_ids)); IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); parser->Receive(cn1_->config_db(), netconf.data(), netconf.length(), 0); task_util::WaitForIdle(); @@ -427,6 +447,34 @@ class ServiceChainTest : public ::testing::Test { } } + void ToggleAllowTransit(BgpServerTest *server, const string &network) { + autogen::VirtualNetworkType *property; + { + task_util::TaskSchedulerLock lock; + IFMapNode *node = ifmap_test_util::IFMapNodeLookup( + server->config_db(), "virtual-network", network); + EXPECT_TRUE(node != NULL); + IFMapObject *obj = node->Find(IFMapOrigin(IFMapOrigin::MAP_SERVER)); + EXPECT_TRUE(obj != NULL); + autogen::VirtualNetwork *vn = + dynamic_cast(obj); + EXPECT_TRUE(vn != NULL); + property = new autogen::VirtualNetworkType; + property->Copy(vn->properties()); + property->allow_transit = !property->allow_transit; + } + ifmap_test_util::IFMapMsgPropertyAdd(server->config_db(), + "virtual-network", network, + "virtual-network-properties", property, 0); + task_util::WaitForIdle(); + } + + void VerifyInstanceIsTransit(BgpServer *server, const string &instance) { + RoutingInstanceMgr *rim = server->routing_instance_mgr(); + const RoutingInstance *rti = rim->GetRoutingInstance(instance); + TASK_UTIL_EXPECT_TRUE(rti->virtual_network_allow_transit()); + } + void Unconfigure() { char config[4096]; snprintf(config, sizeof(config), "%s", config_delete); @@ -583,6 +631,19 @@ class ServiceChainTest : public ::testing::Test { task_util::WaitForIdle(); } + void AddTableConnectedRoute(const string &table, bool ecmp, + const string &prefix, + const string &nexthop1, const string &nexthop2 = "") { + agent_a_1_->AddRoute(table, prefix, nexthop1, 100); + agent_a_2_->AddRoute(table, prefix, nexthop1, 100); + if (ecmp) { + EXPECT_FALSE(nexthop2.empty()); + agent_b_1_->AddRoute(table, prefix, nexthop2, 100); + agent_b_2_->AddRoute(table, prefix, nexthop2, 100); + } + task_util::WaitForIdle(); + } + void DeleteConnectedRoute(bool ecmp = false, const string &prefix = "1.1.2.3/32") { // Add Connected route @@ -601,6 +662,17 @@ class ServiceChainTest : public ::testing::Test { task_util::WaitForIdle(); } + void DeleteTableConnectedRoute(const string &table, bool ecmp, + const string &prefix) { + agent_a_1_->DeleteRoute(table, prefix); + agent_a_2_->DeleteRoute(table, prefix); + if (ecmp) { + agent_b_1_->DeleteRoute(table, prefix); + agent_b_2_->DeleteRoute(table, prefix); + } + task_util::WaitForIdle(); + } + struct PathVerify { string path_id; string path_src; @@ -614,22 +686,22 @@ class ServiceChainTest : public ::testing::Test { } }; - bool MatchResult(BgpServerTest *server, string prefix, - vector verify) { + bool MatchResult(BgpServerTest *server, const string &instance, + const string &prefix, const vector &verify) { task_util::TaskSchedulerLock lock; // Verify number of paths - BgpRoute *svc_route = InetRouteLookup(server, "blue", prefix); + BgpRoute *svc_route = InetRouteLookup(server, instance, prefix); if (!svc_route || svc_route->count() != verify.size()) { return false; } - vector::iterator vit; - Route::PathList::iterator it; + vector::const_iterator vit; + Route::PathList::const_iterator it; for (it = svc_route->GetPathList().begin(), vit = verify.begin(); it != svc_route->GetPathList().end(); it++, vit++) { - BgpPath *path = static_cast(it.operator->()); - BgpAttrPtr attr = path->GetAttr(); + const BgpPath *path = static_cast(it.operator->()); + const BgpAttr *attr = path->GetAttr(); set list = GetTunnelEncapListFromRoute(path); if (BgpPath::PathIdString(path->GetPathId()) != vit->path_id) return false; if (BgpPath::PathSourceString(path->GetSource()) != vit->path_src) return false; @@ -650,12 +722,22 @@ class ServiceChainTest : public ::testing::Test { // Verify each path for specific attribute as per the PathVerify list BgpRoute *rt = InetRouteLookup(server, "blue", prefix); - TASK_UTIL_WAIT_EQ_NO_MSG(MatchResult(server, prefix, verify), + TASK_UTIL_WAIT_EQ_NO_MSG(MatchResult(server, "blue", prefix, verify), true, 1000, 10000, "Wait for correct route in blue.."); LOG(DEBUG, "Prefix " << prefix << "has " << rt->GetPathList().size()); } + void VerifyServiceChainRoute(BgpServerTest *server, const string &instance, + const string &prefix, const vector verify) { + // First wait for the route. + TASK_UTIL_EXPECT_TRUE( + InetRouteLookup(server, instance, prefix) != NULL); + + // Verify each path for specific attribute as per the PathVerify list + TASK_UTIL_EXPECT_TRUE(MatchResult(server, instance, prefix, verify)); + } + string FileRead(const string &filename) { ifstream file(filename.c_str()); string content((istreambuf_iterator(file)), @@ -772,7 +854,8 @@ class ServiceChainTest : public ::testing::Test { boost::scoped_ptr agent_b_2_; boost::scoped_ptr bgp_channel_manager_cn1_; boost::scoped_ptr bgp_channel_manager_cn2_; - const char *connected_table_; + string connected_table_; + bool transparent_; bool aggregate_enable_; bool mx_push_connected_; bool single_si_; @@ -1024,149 +1107,558 @@ TEST_P(ServiceIntergrationParamTest, OriginVn) { DeleteConnectedRoute(true); } -// -// Verify when externally connected route is available as static route. -// -TEST_P(ServiceIntergrationParamTest, StaticRoute) { - // Not applicable - aggregate_enable_ = false; - auto_ptr params; +typedef tr1::tuple TestParams2; - params = - GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); - ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); +class ServiceIntergrationParamTest2 : + public ServiceChainTest, + public ::testing::WithParamInterface { + virtual void SetUp() { + connected_table_ = "blue"; + mx_push_connected_ = false; + single_si_ = false; + aggregate_enable_ = tr1::get<0>(GetParam()); + left_to_right_ = tr1::get<1>(GetParam()); + ServiceChainTest::SetUp(); + } - params = - GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); - ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); - task_util::WaitForIdle(); + virtual void TearDown() { + ServiceChainTest::TearDown(); + } +}; - // Add Connected route - AddConnectedRoute(true); +// +// Verify 2 in-network services on the same compute node. +// +// The RDs used when advertising service chain routes for the 2 service +// instances should be different. The RD is based on the compute node's +// registration id for the service routing instances, rather then the +// connected routing instance. +// +TEST_P(ServiceIntergrationParamTest2, MultipleInNetwork) { + // Add VM routes in red. + agent_a_1_->AddRoute("red", "192.168.1.1/32"); + agent_a_2_->AddRoute("red", "192.168.1.1/32"); task_util::WaitForIdle(); + // Add Connected routes for both service instances. + if (left_to_right_) { + AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); + AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); + } else { + AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); + AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); + } + + // Wait for everything to be processed. TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); - vector path_list; - if (mx_push_connected_) { - PathVerify verify_1("1.2.2.1", "StaticRoute", "1.2.2.1", set(), "blue"); - PathVerify verify_2("7.8.9.1", "StaticRoute", "7.8.9.1", set(), "blue"); - PathVerify verify_3("1.2.2.1", "BGP_XMPP", "1.2.2.1", set(), "blue"); - PathVerify verify_4("7.8.9.1", "BGP_XMPP", "7.8.9.1", set(), "blue"); - path_list.push_back(verify_1); - path_list.push_back(verify_2); - path_list.push_back(verify_3); - path_list.push_back(verify_4); + // Verify service chain routes are replicated to bgp.l3vpn.0. + // Note that agents are registered to blue-i1 with instance id 1. + // Note that agents are registered to blue-i3 with instance id 6. + if (aggregate_enable_) { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); } else { - PathVerify verify_1("88.88.88.88", "StaticRoute", "88.88.88.88", list_of ("gre"), connected_table_); - PathVerify verify_2("99.99.99.99", "StaticRoute", "99.99.99.99", list_of ("gre"), connected_table_); - PathVerify verify_3("88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of ("gre"), connected_table_); - PathVerify verify_4("99.99.99.99", "BGP_XMPP", "99.99.99.99", list_of ("gre"), connected_table_); - path_list.push_back(verify_1); - path_list.push_back(verify_2); - path_list.push_back(verify_3); - path_list.push_back(verify_4); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); } - // Check for ServiceChain route - VerifyServiceChainRoute(cn1_.get(), "10.1.1.0/24", path_list); - VerifyServiceChainRoute(cn2_.get(), "10.1.1.0/24", path_list); + // Delete Connected routes for both service instances. + if (left_to_right_) { + DeleteConnectedRoute(false, "1.1.2.3/32"); + DeleteConnectedRoute(false, "1.1.2.4/32"); + } else { + DeleteConnectedRoute(false, "1.1.2.4/32"); + DeleteConnectedRoute(false, "1.1.2.3/32"); + } - DeleteConnectedRoute(true); + // Delete VM routes in red. + agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); } // -// Verify when externally connected route is available as both static route -// and service chain route +// Verify 2 in-network services scaled on 2 computes nodes each. // -TEST_P(ServiceIntergrationParamTest, DISABLED_SvcStaticRoute) { - // Not applicable - aggregate_enable_ = false; - auto_ptr params; - - params = - GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); - ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); - - params = - GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); - ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); - task_util::WaitForIdle(); - - - // Add external route from MX to a VN which is connected to dest routing instance - AddInetRoute(mx_.get(), NULL, "public", "10.1.1.0/24", 100); +// The RDs used when advertising service chain routes for the 2 service +// instances should be different. The RD is based on the compute node's +// registration id for the service routing instances, rather then the +// connected routing instance. +// +TEST_P(ServiceIntergrationParamTest2, MultipleInNetworkECMP) { + // Add VM routes in red. + agent_a_1_->AddRoute("red", "192.168.1.1/32"); + agent_a_2_->AddRoute("red", "192.168.1.1/32"); task_util::WaitForIdle(); - // Add Connected route - AddConnectedRoute(true); - task_util::WaitForIdle(); + // Add Connected routes for both service instances. + if (left_to_right_) { + AddConnectedRoute(true, "1.1.2.3/32", "8.8.8.8", "9.9.9.9"); + AddConnectedRoute(true, "1.1.2.4/32", "8.8.8.8", "9.9.9.9"); + } else { + AddConnectedRoute(true, "1.1.2.4/32", "8.8.8.8", "9.9.9.9"); + AddConnectedRoute(true, "1.1.2.3/32", "8.8.8.8", "9.9.9.9"); + } + // Wait for everything to be processed. TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); - vector path_list; - if (mx_push_connected_) { - PathVerify verify_1("1.2.2.1", "StaticRoute", "1.2.2.1", set(), "blue"); - PathVerify verify_2("7.8.9.1", "StaticRoute", "7.8.9.1", set(), "blue"); - PathVerify verify_3("1.2.2.1", "SericeChain", "1.2.2.1", set(), "red"); - PathVerify verify_4("7.8.9.1", "SericeChain", "7.8.9.1", set(), "red"); - PathVerify verify_5("1.2.2.1", "BGP_XMPP", "1.2.2.1", set(), "blue"); - PathVerify verify_6("7.8.9.1", "BGP_XMPP", "7.8.9.1", set(), "blue"); - path_list.push_back(verify_1); - path_list.push_back(verify_2); - path_list.push_back(verify_3); - path_list.push_back(verify_4); - path_list.push_back(verify_5); - path_list.push_back(verify_6); + // Verify service chain routes are replicated to bgp.l3vpn.0. + // Note that agents are registered to blue-i1 with instance id 1. + // Note that agents are registered to blue-i3 with instance id 6. + if (aggregate_enable_) { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:6:192.168.1.0/24"); } else { - PathVerify verify_1("88.88.88.88", "StaticRoute", "88.88.88.88", list_of ("gre"), connected_table_); - PathVerify verify_2("99.99.99.99", "StaticRoute", "99.99.99.99", list_of ("gre"), connected_table_); - PathVerify verify_3("88.88.88.88", "SericeChain", "88.88.88.88", list_of ("gre"), "red"); - PathVerify verify_4("99.99.99.99", "SericeChain", "99.99.99.99", list_of ("gre"), "red"); - PathVerify verify_5("88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of ("gre"), connected_table_); - PathVerify verify_6("99.99.99.99", "BGP_XMPP", "99.99.99.99", list_of ("gre"), connected_table_); - path_list.push_back(verify_1); - path_list.push_back(verify_2); - path_list.push_back(verify_3); - path_list.push_back(verify_4); - path_list.push_back(verify_5); - path_list.push_back(verify_6); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:6:192.168.1.1/32"); } - // Check for ServiceChain route - VerifyServiceChainRoute(cn1_.get(), "10.1.1.0/24", path_list); - VerifyServiceChainRoute(cn2_.get(), "10.1.1.0/24", path_list); - - DeleteInetRoute(mx_.get(), NULL, "public", "10.1.1.0/24"); + // Delete Connected routes for both service instances. + if (left_to_right_) { + DeleteConnectedRoute(true, "1.1.2.3/32"); + DeleteConnectedRoute(true, "1.1.2.4/32"); + } else { + DeleteConnectedRoute(true, "1.1.2.4/32"); + DeleteConnectedRoute(true, "1.1.2.3/32"); + } - DeleteConnectedRoute(true); + // Delete VM routes in red. + agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); } -// -// Each Agent has multiple l3 interfaces and instance for static routes is -// created on both compute nodes. // -TEST_P(ServiceIntergrationParamTest, MultipleL3Intf) { - // Not applicable - aggregate_enable_ = false; - mx_push_connected_ = false; - - auto_ptr params = - GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); +// Verify 2 in-network services on the same compute node, in cases where +// subscribe for the service routing instances happens later i.e. after +// the connected route is processed. +// +// The RDs used when advertising service chain routes for the 2 service +// instances should be different. The RD is based on the compute node's +// registration id for the service routing instances, rather then the +// connected routing instance. +// +TEST_P(ServiceIntergrationParamTest2, MultipleInNetworkUnsubscribeSubscribe) { + // Add VM routes in red. + agent_a_1_->AddRoute("red", "192.168.1.1/32"); + agent_a_2_->AddRoute("red", "192.168.1.1/32"); + task_util::WaitForIdle(); - ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); + // Add Connected routes for both service instances. + if (left_to_right_) { + AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); + AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); + } else { + AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); + AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); + } - params = GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); - ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", - "blue-i1", "static-route-entries", params.release(), 0); - task_util::WaitForIdle(); + // Wait for everything to be processed. + TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); + TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); + + // Verify service chain routes are replicated to bgp.l3vpn.0. + // Note that agents are registered to blue-i1 with instance id 1. + // Note that agents are registered to blue-i3 with instance id 6. + if (aggregate_enable_) { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); + } else { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); + } + + // Unsubscribe agents from blue-i1 and blue-i3. + UnsubscribeAgents("blue-i1"); + UnsubscribeAgents("blue-i3"); + + // Verify service chain routes are no longer in bgp.l3vpn.0. + // Note that agents are registered to blue-i1 with instance id 1. + // Note that agents are registered to blue-i3 with instance id 6. + if (aggregate_enable_) { + VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); + } else { + VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); + } + + // Subscribe agents to blue-i1 and blue-i3. + SubscribeAgents("blue-i1", 1); + SubscribeAgents("blue-i3", 6); + + // Verify service chain routes are replicated to bgp.l3vpn.0. + // Note that agents are registered to blue-i1 with instance id 1. + // Note that agents are registered to blue-i3 with instance id 6. + if (aggregate_enable_) { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); + } else { + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); + VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); + } + + // Delete Connected routes for both service instances. + if (left_to_right_) { + DeleteConnectedRoute(false, "1.1.2.3/32"); + DeleteConnectedRoute(false, "1.1.2.4/32"); + } else { + DeleteConnectedRoute(false, "1.1.2.4/32"); + DeleteConnectedRoute(false, "1.1.2.3/32"); + } + + // Delete VM routes in red. + agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); +} + +typedef tr1::tuple TestParams3; + +class ServiceIntergrationParamTest3 : + public ServiceChainTest, + public ::testing::WithParamInterface { + virtual void SetUp() { + connected_table_ = "multiple"; + mx_push_connected_ = false; + single_si_ = true; + transparent_ = tr1::get<0>(GetParam()); + aggregate_enable_ = tr1::get<1>(GetParam()); + left_to_right_ = false; + ServiceChainTest::SetUp(); + } + + virtual void TearDown() { + ServiceChainTest::TearDown(); + } +}; + +TEST_P(ServiceIntergrationParamTest3, BidirectionalChain) { + string blue_conn_table = transparent_ ? "blue-i1" : "blue"; + string red_conn_table = transparent_ ? "red-i2" : "red"; + + // Add more specifics + agent_a_1_->AddRoute("red", "192.168.1.1/32"); + agent_a_2_->AddRoute("red", "192.168.1.1/32"); + agent_a_1_->AddRoute("blue", "192.168.0.1/32"); + agent_a_2_->AddRoute("blue", "192.168.0.1/32"); + task_util::WaitForIdle(); + + // Add Connected routes + AddTableConnectedRoute(blue_conn_table, false, "1.1.2.3/32", "88.88.88.88"); + AddTableConnectedRoute(red_conn_table, false, "1.1.2.1/32", "66.66.66.66"); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); + TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); + + vector pl_blue; + PathVerify verify_blue1( + "88.88.88.88", "SericeChain", "88.88.88.88", list_of("gre"), "red"); + PathVerify verify_blue2( + "88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of("gre"), "red"); + pl_blue.push_back(verify_blue1); + pl_blue.push_back(verify_blue2); + + vector pl_red; + PathVerify verify_red1( + "66.66.66.66", "SericeChain", "66.66.66.66", list_of("gre"), "blue"); + PathVerify verify_red2( + "66.66.66.66", "BGP_XMPP", "66.66.66.66", list_of("gre"), "blue"); + pl_red.push_back(verify_red1); + pl_red.push_back(verify_red2); + + if (aggregate_enable_) { + VerifyServiceChainRoute(cn1_.get(), "blue", "192.168.1.0/24", pl_blue); + VerifyServiceChainRoute(cn2_.get(), "blue", "192.168.1.0/24", pl_blue); + VerifyServiceChainRoute(cn1_.get(), "red", "192.168.0.0/24", pl_red); + VerifyServiceChainRoute(cn2_.get(), "red", "192.168.0.0/24", pl_red); + } else { + VerifyServiceChainRoute(cn1_.get(), "blue", "192.168.1.1/32", pl_blue); + VerifyServiceChainRoute(cn2_.get(), "blue", "192.168.1.1/32", pl_blue); + VerifyServiceChainRoute(cn1_.get(), "red", "192.168.0.1/32", pl_red); + VerifyServiceChainRoute(cn2_.get(), "red", "192.168.0.1/32", pl_red); + } + + // Delete Connected routes + DeleteTableConnectedRoute(blue_conn_table, false, "1.1.2.3/32"); + DeleteTableConnectedRoute(red_conn_table, false, "1.1.2.1/32"); + task_util::WaitForIdle(); + + // Delete more specifics + agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_1_->DeleteRoute("blue", "192.168.0.1/32"); + agent_a_2_->DeleteRoute("blue", "192.168.0.1/32"); + task_util::WaitForIdle(); +} + +TEST_P(ServiceIntergrationParamTest3, BidirectionalChainWithTransitNetwork) { + ToggleAllowTransit(cn1_.get(), "red"); + ToggleAllowTransit(cn2_.get(), "red"); + VerifyInstanceIsTransit(cn1_.get(), "red"); + VerifyInstanceIsTransit(cn2_.get(), "red"); + + string blue_conn_table = transparent_ ? "blue-i1" : "blue"; + string red_conn_table = transparent_ ? "red-i2" : "red"; + + // Add more specifics + agent_a_1_->AddRoute("red", "192.168.1.1/32"); + agent_a_2_->AddRoute("red", "192.168.1.1/32"); + agent_a_1_->AddRoute("blue", "192.168.0.1/32"); + agent_a_2_->AddRoute("blue", "192.168.0.1/32"); + task_util::WaitForIdle(); + + // Add Connected routes + AddTableConnectedRoute(blue_conn_table, false, "1.1.2.3/32", "88.88.88.88"); + AddTableConnectedRoute(red_conn_table, false, "1.1.2.1/32", "66.66.66.66"); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); + TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); + + vector pl_blue; + PathVerify verify_blue1( + "88.88.88.88", "SericeChain", "88.88.88.88", list_of("gre"), "red"); + PathVerify verify_blue2( + "88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of("gre"), "red"); + pl_blue.push_back(verify_blue1); + pl_blue.push_back(verify_blue2); + + vector pl_red; + PathVerify verify_red1( + "66.66.66.66", "SericeChain", "66.66.66.66", list_of("gre"), "blue"); + PathVerify verify_red2( + "66.66.66.66", "BGP_XMPP", "66.66.66.66", list_of("gre"), "blue"); + pl_red.push_back(verify_red1); + pl_red.push_back(verify_red2); + + if (aggregate_enable_) { + VerifyServiceChainRoute(cn1_.get(), "blue", "192.168.1.0/24", pl_blue); + VerifyServiceChainRoute(cn2_.get(), "blue", "192.168.1.0/24", pl_blue); + VerifyServiceChainRoute(cn1_.get(), "red", "192.168.0.0/24", pl_red); + VerifyServiceChainRoute(cn2_.get(), "red", "192.168.0.0/24", pl_red); + } else { + VerifyServiceChainRoute(cn1_.get(), "blue", "192.168.1.1/32", pl_blue); + VerifyServiceChainRoute(cn2_.get(), "blue", "192.168.1.1/32", pl_blue); + VerifyServiceChainRoute(cn1_.get(), "red", "192.168.0.1/32", pl_red); + VerifyServiceChainRoute(cn2_.get(), "red", "192.168.0.1/32", pl_red); + } + + // Delete Connected routes + DeleteTableConnectedRoute(blue_conn_table, false, "1.1.2.3/32"); + DeleteTableConnectedRoute(red_conn_table, false, "1.1.2.1/32"); + task_util::WaitForIdle(); + + // Delete more specifics + agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); + agent_a_1_->DeleteRoute("blue", "192.168.0.1/32"); + agent_a_2_->DeleteRoute("blue", "192.168.0.1/32"); + task_util::WaitForIdle(); +} + +class ServiceIntergrationParamTest4 : + public ServiceChainTest, + public ::testing::WithParamInterface { + virtual void SetUp() { + connected_table_ = "blue"; + mx_push_connected_ = GetParam(); + single_si_ = true; + transparent_ = false; + aggregate_enable_ = false; + left_to_right_ = false; + ServiceChainTest::SetUp(); + } + + virtual void TearDown() { + ServiceChainTest::TearDown(); + } +}; + +// +// Verify when externally connected route is available as static route. +// +TEST_P(ServiceIntergrationParamTest4, StaticRoute) { + auto_ptr params; + + params = + GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + + params = + GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + task_util::WaitForIdle(); + + // Add Connected route + AddConnectedRoute(true); + task_util::WaitForIdle(); + + vector path_list; + if (mx_push_connected_) { + PathVerify verify_1( + "1.2.2.1", "StaticRoute", "1.2.2.1", set(), "blue"); + PathVerify verify_2( + "7.8.9.1", "StaticRoute", "7.8.9.1", set(), "blue"); + PathVerify verify_3( + "1.2.2.1", "BGP_XMPP", "1.2.2.1", set(), "blue"); + PathVerify verify_4( + "7.8.9.1", "BGP_XMPP", "7.8.9.1", set(), "blue"); + path_list.push_back(verify_1); + path_list.push_back(verify_2); + path_list.push_back(verify_3); + path_list.push_back(verify_4); + } else { + PathVerify verify_1( + "88.88.88.88", "StaticRoute", "88.88.88.88", list_of("gre"), "blue"); + PathVerify verify_2( + "99.99.99.99", "StaticRoute", "99.99.99.99", list_of("gre"), "blue"); + PathVerify verify_3( + "88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of("gre"), "blue"); + PathVerify verify_4( + "99.99.99.99", "BGP_XMPP", "99.99.99.99", list_of("gre"), "blue"); + path_list.push_back(verify_1); + path_list.push_back(verify_2); + path_list.push_back(verify_3); + path_list.push_back(verify_4); + } + + // Check for ServiceChain route + VerifyServiceChainRoute(cn1_.get(), "blue-i1", "10.1.1.0/24", path_list); + VerifyServiceChainRoute(cn2_.get(), "blue-i1", "10.1.1.0/24", path_list); + + // Add Connected route + DeleteConnectedRoute(true); + task_util::WaitForIdle(); +} + +// +// Verify when externally connected route is available as both static route +// and service chain route +// +TEST_P(ServiceIntergrationParamTest4, DISABLED_SvcStaticRoute) { + auto_ptr params; + + params = + GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + + params = + GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + task_util::WaitForIdle(); + + + // Add external route from MX to a VN which is connected to dest routing instance + AddInetRoute(mx_.get(), NULL, "public", "10.1.1.0/24", 100); + task_util::WaitForIdle(); + + // Add Connected route + AddConnectedRoute(true); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); + TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); + + vector path_list; + if (mx_push_connected_) { + PathVerify verify_1("1.2.2.1", "StaticRoute", "1.2.2.1", set(), "blue"); + PathVerify verify_2("7.8.9.1", "StaticRoute", "7.8.9.1", set(), "blue"); + PathVerify verify_3("1.2.2.1", "SericeChain", "1.2.2.1", set(), "red"); + PathVerify verify_4("7.8.9.1", "SericeChain", "7.8.9.1", set(), "red"); + PathVerify verify_5("1.2.2.1", "BGP_XMPP", "1.2.2.1", set(), "blue"); + PathVerify verify_6("7.8.9.1", "BGP_XMPP", "7.8.9.1", set(), "blue"); + path_list.push_back(verify_1); + path_list.push_back(verify_2); + path_list.push_back(verify_3); + path_list.push_back(verify_4); + path_list.push_back(verify_5); + path_list.push_back(verify_6); + } else { + PathVerify verify_1("88.88.88.88", "StaticRoute", "88.88.88.88", list_of("gre"), "blue"); + PathVerify verify_2("99.99.99.99", "StaticRoute", "99.99.99.99", list_of("gre"), "blue"); + PathVerify verify_3("88.88.88.88", "SericeChain", "88.88.88.88", list_of("gre"), "red"); + PathVerify verify_4("99.99.99.99", "SericeChain", "99.99.99.99", list_of("gre"), "red"); + PathVerify verify_5("88.88.88.88", "BGP_XMPP", "88.88.88.88", list_of("gre"), "blue"); + PathVerify verify_6("99.99.99.99", "BGP_XMPP", "99.99.99.99", list_of("gre"), "blue"); + path_list.push_back(verify_1); + path_list.push_back(verify_2); + path_list.push_back(verify_3); + path_list.push_back(verify_4); + path_list.push_back(verify_5); + path_list.push_back(verify_6); + } + + // Check for ServiceChain route + VerifyServiceChainRoute(cn1_.get(), "10.1.1.0/24", path_list); + VerifyServiceChainRoute(cn2_.get(), "10.1.1.0/24", path_list); + + DeleteInetRoute(mx_.get(), NULL, "public", "10.1.1.0/24"); + + DeleteConnectedRoute(true); +} + +INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest, + ::testing::Combine(::testing::Bool(), ::testing::Bool(), ::testing::Bool())); + +INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest2, + ::testing::Combine(::testing::Bool(), ::testing::Bool())); + +INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest3, + ::testing::Combine(::testing::Bool(), ::testing::Bool())); + +INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest4, + ::testing::Bool()); + +// +// Each Agent has multiple l3 interfaces and instance for static routes is +// created on both compute nodes. +// +TEST_F(ServiceChainTest, StaticRouteMultipleL3Intf) { + auto_ptr params = + GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + + ifmap_test_util::IFMapMsgPropertyAdd(cn1_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + + params = GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); + ifmap_test_util::IFMapMsgPropertyAdd(cn2_->config_db(), "routing-instance", + "blue-i1", "static-route-entries", params.release(), 0); + task_util::WaitForIdle(); // Add Connected route NextHops nexthops; @@ -1217,11 +1709,7 @@ TEST_P(ServiceIntergrationParamTest, MultipleL3Intf) { // both compute nodes. // Tests both static route and service chain functionality. // -TEST_P(ServiceIntergrationParamTest, DISABLED_MultipleL3Intf) { - // Not applicable - aggregate_enable_ = false; - mx_push_connected_ = false; - +TEST_F(ServiceChainTest, DISABLED_StaticRouteMultipleL3Intf) { auto_ptr params = GetStaticRouteConfig("controller/src/bgp/testdata/static_route_8.xml"); @@ -1292,247 +1780,6 @@ TEST_P(ServiceIntergrationParamTest, DISABLED_MultipleL3Intf) { DeleteConnectedRoute(true); } -typedef tr1::tuple TestParams2; - -class ServiceIntergrationParamTest2 : - public ServiceChainTest, - public ::testing::WithParamInterface { - virtual void SetUp() { - connected_table_ = "blue"; - mx_push_connected_ = false; - single_si_ = false; - aggregate_enable_ = tr1::get<0>(GetParam()); - left_to_right_ = tr1::get<1>(GetParam()); - ServiceChainTest::SetUp(); - } - - virtual void TearDown() { - ServiceChainTest::TearDown(); - } -}; - -// -// Verify 2 in-network services on the same compute node. -// -// The RDs used when advertising service chain routes for the 2 service -// instances should be different. The RD is based on the compute node's -// registration id for the service routing instances, rather then the -// connected routing instance. -// -TEST_P(ServiceIntergrationParamTest2, MultipleInNetwork) { - // Add VM routes in red. - agent_a_1_->AddRoute("red", "192.168.1.1/32"); - agent_a_2_->AddRoute("red", "192.168.1.1/32"); - task_util::WaitForIdle(); - - // Add Connected routes for both service instances. - if (left_to_right_) { - AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); - AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); - } else { - AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); - AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); - } - - // Wait for everything to be processed. - TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); - TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); - - // Verify service chain routes are replicated to bgp.l3vpn.0. - // Note that agents are registered to blue-i1 with instance id 1. - // Note that agents are registered to blue-i3 with instance id 6. - if (aggregate_enable_) { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); - } else { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); - } - - // Delete Connected routes for both service instances. - if (left_to_right_) { - DeleteConnectedRoute(false, "1.1.2.3/32"); - DeleteConnectedRoute(false, "1.1.2.4/32"); - } else { - DeleteConnectedRoute(false, "1.1.2.4/32"); - DeleteConnectedRoute(false, "1.1.2.3/32"); - } - - // Delete VM routes in red. - agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); - agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); -} - -// -// Verify 2 in-network services scaled on 2 computes nodes each. -// -// The RDs used when advertising service chain routes for the 2 service -// instances should be different. The RD is based on the compute node's -// registration id for the service routing instances, rather then the -// connected routing instance. -// -TEST_P(ServiceIntergrationParamTest2, MultipleInNetworkECMP) { - // Add VM routes in red. - agent_a_1_->AddRoute("red", "192.168.1.1/32"); - agent_a_2_->AddRoute("red", "192.168.1.1/32"); - task_util::WaitForIdle(); - - // Add Connected routes for both service instances. - if (left_to_right_) { - AddConnectedRoute(true, "1.1.2.3/32", "8.8.8.8", "9.9.9.9"); - AddConnectedRoute(true, "1.1.2.4/32", "8.8.8.8", "9.9.9.9"); - } else { - AddConnectedRoute(true, "1.1.2.4/32", "8.8.8.8", "9.9.9.9"); - AddConnectedRoute(true, "1.1.2.3/32", "8.8.8.8", "9.9.9.9"); - } - - // Wait for everything to be processed. - TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); - TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); - - // Verify service chain routes are replicated to bgp.l3vpn.0. - // Note that agents are registered to blue-i1 with instance id 1. - // Note that agents are registered to blue-i3 with instance id 6. - if (aggregate_enable_) { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:6:192.168.1.0/24"); - } else { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "9.9.9.9:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "9.9.9.9:6:192.168.1.1/32"); - } - - // Delete Connected routes for both service instances. - if (left_to_right_) { - DeleteConnectedRoute(true, "1.1.2.3/32"); - DeleteConnectedRoute(true, "1.1.2.4/32"); - } else { - DeleteConnectedRoute(true, "1.1.2.4/32"); - DeleteConnectedRoute(true, "1.1.2.3/32"); - } - - // Delete VM routes in red. - agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); - agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); -} - -// -// Verify 2 in-network services on the same compute node, in cases where -// subscribe for the service routing instances happens later i.e. after -// the connected route is processed. -// -// The RDs used when advertising service chain routes for the 2 service -// instances should be different. The RD is based on the compute node's -// registration id for the service routing instances, rather then the -// connected routing instance. -// -TEST_P(ServiceIntergrationParamTest2, MultipleInNetworkUnsubscribeSubscribe) { - // Add VM routes in red. - agent_a_1_->AddRoute("red", "192.168.1.1/32"); - agent_a_2_->AddRoute("red", "192.168.1.1/32"); - task_util::WaitForIdle(); - - // Add Connected routes for both service instances. - if (left_to_right_) { - AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); - AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); - } else { - AddConnectedRoute(false, "1.1.2.4/32", "8.8.8.8"); - AddConnectedRoute(false, "1.1.2.3/32", "8.8.8.8"); - } - - // Wait for everything to be processed. - TASK_UTIL_EXPECT_TRUE(cn1_.get()->service_chain_mgr()->IsQueueEmpty()); - TASK_UTIL_EXPECT_TRUE(cn2_.get()->service_chain_mgr()->IsQueueEmpty()); - - // Verify service chain routes are replicated to bgp.l3vpn.0. - // Note that agents are registered to blue-i1 with instance id 1. - // Note that agents are registered to blue-i3 with instance id 6. - if (aggregate_enable_) { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); - } else { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); - } - - // Unsubscribe agents from blue-i1 and blue-i3. - UnsubscribeAgents("blue-i1"); - UnsubscribeAgents("blue-i3"); - - // Verify service chain routes are no longer in bgp.l3vpn.0. - // Note that agents are registered to blue-i1 with instance id 1. - // Note that agents are registered to blue-i3 with instance id 6. - if (aggregate_enable_) { - VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); - } else { - VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteNoExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteNoExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); - } - - // Subscribe agents to blue-i1 and blue-i3. - SubscribeAgents("blue-i1", 1); - SubscribeAgents("blue-i3", 6); - - // Verify service chain routes are replicated to bgp.l3vpn.0. - // Note that agents are registered to blue-i1 with instance id 1. - // Note that agents are registered to blue-i3 with instance id 6. - if (aggregate_enable_) { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.0/24"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.0/24"); - } else { - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn1_.get(), "8.8.8.8:6:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:1:192.168.1.1/32"); - VerifyInetVpnRouteExists(cn2_.get(), "8.8.8.8:6:192.168.1.1/32"); - } - - // Delete Connected routes for both service instances. - if (left_to_right_) { - DeleteConnectedRoute(false, "1.1.2.3/32"); - DeleteConnectedRoute(false, "1.1.2.4/32"); - } else { - DeleteConnectedRoute(false, "1.1.2.4/32"); - DeleteConnectedRoute(false, "1.1.2.3/32"); - } - - // Delete VM routes in red. - agent_a_1_->DeleteRoute("red", "192.168.1.1/32"); - agent_a_2_->DeleteRoute("red", "192.168.1.1/32"); -} - -INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest, - ::testing::Combine(::testing::Bool(), ::testing::Bool(), ::testing::Bool())); - -INSTANTIATE_TEST_CASE_P(Instance, ServiceIntergrationParamTest2, - ::testing::Combine(::testing::Bool(), ::testing::Bool())); - class TestEnvironment : public ::testing::Environment { virtual ~TestEnvironment() { } }; diff --git a/src/bgp/testdata/service_chain_6.xml b/src/bgp/testdata/service_chain_6.xml new file mode 100644 index 00000000000..ddf073f8288 --- /dev/null +++ b/src/bgp/testdata/service_chain_6.xml @@ -0,0 +1,7 @@ + + + blue + red + 192.168.0.0/24 + 1.1.2.1 + From 71e28617a0bd03cfacab056b4ec6e7a02eecc279 Mon Sep 17 00:00:00 2001 From: Pedro Marques Date: Wed, 15 Oct 2014 22:14:49 +0000 Subject: [PATCH 029/218] Add vrouter-instance ServiceInstanceType Change-Id: Iab21f83743e100cd89471ee03ccba6110abbe551 --- src/schema/vnc_cfg.xsd | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd index 416553f5d5f..deede79ab91 100644 --- a/src/schema/vnc_cfg.xsd +++ b/src/schema/vnc_cfg.xsd @@ -1107,9 +1107,35 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + + ServiceVirtualizationType defines how a service instance is + managed. + * virtual-machine instances are managed by openstack nova. + * network-namespace instances are scheduled by service-monitor + into a functioning virtual-router in the cluster. + * vrouter-instance type instance are scheduled in a specific + virtual-router according to the virtual-router-id parameter in + the service instance. + + + + + + + + + + For vrouter managed instances, this indicates the mechanism used + to manage the instance. + + + + + @@ -1124,6 +1150,15 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + + + + Opaque string (typically in json format) used to spawn a + vrouter-instance. + + + @@ -1139,6 +1174,14 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + + + The uuid of a virtual-router object in which to spawn a + service-instance of type vrouter-instance. + + + From d3c093b3d70aeb3cbadac1157e01c2083ddbea3c Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Mon, 13 Oct 2014 16:42:00 -0700 Subject: [PATCH 030/218] Cleanup and refactor code in service_chain_test.cc Following changes have been implemented: - Use using instead of using namespace - Add and use helper methods for creating peers and configuring chains - Add and use helper methods for verfification of routes and paths - Consolidate use of task_util::WaitForIdle to a few helper methods Change-Id: I33ccdb0b988fec768bb5c44b1de5d5c91fdd8bb3 --- src/bgp/test/service_chain_test.cc | 2416 +++++++--------------------- 1 file changed, 616 insertions(+), 1800 deletions(-) diff --git a/src/bgp/test/service_chain_test.cc b/src/bgp/test/service_chain_test.cc index 12b33dc7cac..04f8fd09493 100644 --- a/src/bgp/test/service_chain_test.cc +++ b/src/bgp/test/service_chain_test.cc @@ -2,10 +2,6 @@ * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. */ -#include "bgp/routing-instance/service_chaining.h" -#include "bgp/routing-instance/routing_instance.h" -#include "bgp/routing-instance/routepath_replicator.h" - #include #include @@ -15,7 +11,6 @@ #include #include "base/test/task_test_util.h" -#include "bgp/bgp_config.h" #include "bgp/bgp_config_parser.h" #include "bgp/bgp_log.h" #include "bgp/bgp_sandesh.h" @@ -24,6 +19,9 @@ #include "bgp/l3vpn/inetvpn_route.h" #include "bgp/l3vpn/inetvpn_table.h" #include "bgp/origin-vn/origin_vn.h" +#include "bgp/routing-instance/service_chaining.h" +#include "bgp/routing-instance/routing_instance.h" +#include "bgp/routing-instance/routepath_replicator.h" #include "bgp/security_group/security_group.h" #include "bgp/tunnel_encap/tunnel_encap.h" #include "bgp/test/bgp_test_util.h" @@ -38,19 +36,32 @@ #include "schema/vnc_cfg_types.h" #include "testing/gunit.h" -using namespace std; using boost::assign::list_of; using boost::assign::map_list_of; -using namespace pugi; +using pugi::xml_document; +using pugi::xml_node; +using pugi::xml_parse_result; +using std::auto_ptr; +using std::cout; +using std::endl; +using std::ifstream; +using std::istreambuf_iterator; +using std::istringstream; +using std::multimap; +using std::set; +using std::sort; +using std::string; +using std::stringstream; +using std::vector; class BgpPeerMock : public IPeer { public: BgpPeerMock(const Ip4Address &address) : address_(address) { } virtual ~BgpPeerMock() { } - virtual std::string ToString() const { + virtual string ToString() const { return address_.to_string(); } - virtual std::string ToUVEKey() const { + virtual string ToUVEKey() const { return address_.to_string(); } virtual bool SendUpdate(const uint8_t *msg, size_t msgsize) { @@ -77,7 +88,7 @@ class BgpPeerMock : public IPeer { virtual uint32_t bgp_identifier() const { return htonl(address_.to_ulong()); } - virtual const std::string GetStateName() const { + virtual const string GetStateName() const { return ""; } virtual void UpdateRefCount(int count) const { } @@ -103,11 +114,17 @@ class ServiceChainTest : public ::testing::Test { bgp_schema_Server_ModuleInit(&config_db_, &config_graph_); vnc_cfg_Server_ModuleInit(&config_db_, &config_graph_); } + ~ServiceChainTest() { STLDeleteValues(&peers_); } virtual void SetUp() { + CreatePeer("192.168.0.1"); + CreatePeer("192.168.0.2"); + CreatePeer("192.168.0.3"); + CreatePeer("192.168.0.4"); + IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); bgp_schema_ParserInit(parser); vnc_cfg_ParserInit(parser); @@ -135,6 +152,18 @@ class ServiceChainTest : public ::testing::Test { task_util::WaitForIdle(); } + string ParseConfigFile(const string &filename) { + string content = FileRead(filename); + parser_.Parse(content); + task_util::WaitForIdle(); + return content; + } + + void ParseConfigString(const string &content) { + parser_.Parse(content); + task_util::WaitForIdle(); + } + void VerifyNetworkConfig(const vector &instance_names) { for (vector::const_iterator iter = instance_names.begin(); iter != instance_names.end(); ++iter) { @@ -146,6 +175,12 @@ class ServiceChainTest : public ::testing::Test { } } + void CreatePeer(const string &address) { + boost::system::error_code ec; + peers_.push_back(new BgpPeerMock(Ip4Address::from_string(address, ec))); + assert(ec.value() == 0); + } + void DisableServiceChainQ() { bgp_server_->service_chain_mgr()->DisableQueue(); } @@ -153,13 +188,14 @@ class ServiceChainTest : public ::testing::Test { void EnableServiceChainQ() { bgp_server_->service_chain_mgr()->EnableQueue(); } + void AddInetRoute(IPeer *peer, const string &instance_name, const string &prefix, int localpref, - std::vector commlist = std::vector(), - std::vector sglist = std::vector(), - std::set encap = std::set(), - string nexthop="7.8.9.1", - uint32_t flags=0, int label=0) { + vector commlist = vector(), + vector sglist = vector(), + set encap = set(), + string nexthop = "7.8.9.1", + uint32_t flags = 0, int label = 0) { boost::system::error_code error; Ip4Prefix nlri = Ip4Prefix::FromString(prefix, &error); EXPECT_FALSE(error); @@ -184,12 +220,12 @@ class ServiceChainTest : public ::testing::Test { } ExtCommunitySpec ext_comm; - for(std::vector::iterator it = sglist.begin(); + for (vector::iterator it = sglist.begin(); it != sglist.end(); it++) { SecurityGroup sgid(0, *it); ext_comm.communities.push_back(sgid.GetExtCommunityValue()); } - for(std::set::iterator it = encap.begin(); + for (set::iterator it = encap.begin(); it != encap.end(); it++) { TunnelEncap tunnel_encap(*it); ext_comm.communities.push_back(tunnel_encap.GetExtCommunityValue()); @@ -228,10 +264,10 @@ class ServiceChainTest : public ::testing::Test { void AddInetVpnRoute(IPeer *peer, const string &instance_name, const string &prefix, int localpref, - std::vector sglist = std::vector(), - std::set encap = std::set(), - string nexthop="7.8.9.1", - uint32_t flags=0, int label=0) { + vector sglist = vector(), + set encap = set(), + string nexthop = "7.8.9.1", + uint32_t flags = 0, int label = 0) { BgpTable *table = static_cast( bgp_server_->database()->FindTable(instance_name + ".inet.0")); ASSERT_TRUE(table != NULL); @@ -269,12 +305,12 @@ class ServiceChainTest : public ::testing::Test { uint64_t extcomm_value = get_value(target.GetExtCommunity().begin(), 8); ExtCommunitySpec extcomm_spec; extcomm_spec.communities.push_back(extcomm_value); - for(std::vector::iterator it = sglist.begin(); + for (vector::iterator it = sglist.begin(); it != sglist.end(); it++) { SecurityGroup sgid(0, *it); extcomm_spec.communities.push_back(sgid.GetExtCommunityValue()); } - for(std::set::iterator it = encap.begin(); + for (set::iterator it = encap.begin(); it != encap.end(); it++) { TunnelEncap tunnel_encap(*it); extcomm_spec.communities.push_back(tunnel_encap.GetExtCommunityValue()); @@ -296,8 +332,8 @@ class ServiceChainTest : public ::testing::Test { void AddInetVpnRoute(IPeer *peer, const vector &instance_names, const string &prefix, int localpref, - string nexthop="7.8.9.1", - uint32_t flags=0, int label=0) { + string nexthop = "7.8.9.1", + uint32_t flags = 0, int label = 0) { RoutingInstance *rtinstance = ri_mgr_->GetRoutingInstance(instance_names[0]); ASSERT_TRUE(rtinstance != NULL); @@ -379,10 +415,10 @@ class ServiceChainTest : public ::testing::Test { } void AddConnectedRoute(IPeer *peer, const string &prefix, - int localpref, string nexthop="7.8.9.1", - uint32_t flags=0, int label=0, - std::vector sglist = std::vector(), - std::set encap = std::set()) { + int localpref, string nexthop = "7.8.9.1", + uint32_t flags = 0, int label = 0, + vector sglist = vector(), + set encap = set()) { string connected_table = service_is_transparent_ ? "blue-i1" : "blue"; if (connected_rt_is_inetvpn_) { AddInetVpnRoute(peer, connected_table, prefix, @@ -391,13 +427,14 @@ class ServiceChainTest : public ::testing::Test { AddInetRoute(peer, connected_table, prefix, localpref, vector(), sglist, encap, nexthop, flags, label); } + task_util::WaitForIdle(); } void AddConnectedRoute(int chain_idx, IPeer *peer, const string &prefix, - int localpref, string nexthop="7.8.9.1", - uint32_t flags=0, int label=0, - std::vector sglist = std::vector(), - std::set encap = std::set()) { + int localpref, string nexthop = "7.8.9.1", + uint32_t flags = 0, int label = 0, + vector sglist = vector(), + set encap = set()) { assert(1 <= chain_idx && chain_idx <= 3); string connected_table; if (chain_idx == 1) { @@ -414,6 +451,7 @@ class ServiceChainTest : public ::testing::Test { AddInetRoute(peer, connected_table, prefix, localpref, vector(), sglist, encap, nexthop, flags, label); } + task_util::WaitForIdle(); } void DeleteConnectedRoute(IPeer *peer, const string &prefix) { @@ -423,6 +461,7 @@ class ServiceChainTest : public ::testing::Test { } else { DeleteInetRoute(peer, connected_table, prefix); } + task_util::WaitForIdle(); } void DeleteConnectedRoute(int chain_idx, IPeer *peer, const string &prefix) { @@ -440,6 +479,7 @@ class ServiceChainTest : public ::testing::Test { } else { DeleteInetRoute(peer, connected_table, prefix); } + task_util::WaitForIdle(); } int RouteCount(const string &instance_name) const { @@ -483,6 +523,141 @@ class ServiceChainTest : public ::testing::Test { TASK_UTIL_EXPECT_TRUE(InetRouteLookup(instance, prefix) == NULL); } + void VerifyInetRouteIsDeleted(const string &instance, + const string &prefix) { + TASK_UTIL_EXPECT_TRUE(InetRouteLookup(instance, prefix) != NULL); + BgpRoute *rt = InetRouteLookup(instance, prefix); + TASK_UTIL_EXPECT_TRUE(rt->IsDeleted()); + } + + bool MatchInetPathAttributes(const BgpPath *path, + const string &path_id, const string &origin_vn, int label, + const vector sg_ids, const set tunnel_encaps) { + BgpAttrPtr attr = path->GetAttr(); + if (attr->nexthop().to_v4().to_string() != path_id) + return false; + if (GetOriginVnFromRoute(path) != origin_vn) + return false; + if (label && path->GetLabel() != label) + return false; + if (sg_ids.size()) { + vector path_sg_ids = GetSGIDListFromRoute(path); + if (path_sg_ids.size() != sg_ids.size()) + return false; + for (vector::const_iterator + it1 = path_sg_ids.begin(), it2 = sg_ids.begin(); + it1 != path_sg_ids.end() && it2 != sg_ids.end(); + ++it1, ++it2) { + if (*it1 != *it2) + return false; + } + } + if (tunnel_encaps.size()) { + set path_tunnel_encaps = GetTunnelEncapListFromRoute(path); + if (path_tunnel_encaps != tunnel_encaps) + return false; + } + + return true; + } + + bool CheckInetPathAttributes(const string &instance, const string &prefix, + const string &path_id, const string &origin_vn, int label, + const vector sg_ids, const set tunnel_encaps) { + task_util::TaskSchedulerLock lock; + BgpRoute *route = InetRouteLookup(instance, prefix); + if (!route) + return false; + for (Route::PathList::iterator it = route->GetPathList().begin(); + it != route->GetPathList().end(); ++it) { + const BgpPath *path = static_cast(it.operator->()); + if (BgpPath::PathIdString(path->GetPathId()) != path_id) + continue; + if (MatchInetPathAttributes( + path, path_id, origin_vn, label, sg_ids, tunnel_encaps)) { + return true; + } + return false; + } + + return false; + } + + void VerifyInetPathAttributes(const string &instance, + const string &prefix, const string &path_id, const string &origin_vn, + const set tunnel_encaps) { + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(CheckInetPathAttributes(instance, prefix, + path_id, origin_vn, 0, vector(), tunnel_encaps)); + } + + bool CheckInetRouteAttributes(const string &instance, const string &prefix, + const vector &path_ids, const string &origin_vn, int label, + const vector sg_ids, const set tunnel_encaps) { + task_util::TaskSchedulerLock lock; + BgpRoute *route = InetRouteLookup(instance, prefix); + if (!route) + return false; + if (route->count() != path_ids.size()) + return false; + for (Route::PathList::iterator it = route->GetPathList().begin(); + it != route->GetPathList().end(); ++it) { + bool found = false; + const BgpPath *path = static_cast(it.operator->()); + BOOST_FOREACH(const string &path_id, path_ids) { + if (BgpPath::PathIdString(path->GetPathId()) != path_id) + continue; + found = true; + if (MatchInetPathAttributes( + path, path_id, origin_vn, label, sg_ids, tunnel_encaps)) { + break; + } + return false; + } + if (!found) + return false; + } + + return true; + } + + void VerifyInetRouteAttributes(const string &instance, + const string &prefix, const string &path_id, const string &origin_vn, + int label = 0) { + task_util::WaitForIdle(); + vector path_ids = list_of(path_id); + TASK_UTIL_EXPECT_TRUE(CheckInetRouteAttributes( + instance, prefix, path_ids, origin_vn, label, vector(), + set())); + } + + void VerifyInetRouteAttributes(const string &instance, const string &prefix, + const vector &path_ids, const string &origin_vn) { + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(CheckInetRouteAttributes( + instance, prefix, path_ids, origin_vn, 0, vector(), + set())); + } + + void VerifyInetRouteAttributes(const string &instance, + const string &prefix, const string &path_id, const string &origin_vn, + const vector sg_ids) { + task_util::WaitForIdle(); + vector path_ids = list_of(path_id); + TASK_UTIL_EXPECT_TRUE(CheckInetRouteAttributes( + instance, prefix, path_ids, origin_vn, 0, sg_ids, set())); + } + + void VerifyInetRouteAttributes(const string &instance, + const string &prefix, const string &path_id, const string &origin_vn, + const set tunnel_encaps) { + task_util::WaitForIdle(); + vector path_ids = list_of(path_id); + TASK_UTIL_EXPECT_TRUE(CheckInetRouteAttributes( + instance, prefix, path_ids, origin_vn, 0, vector(), + tunnel_encaps)); + } + string FileRead(const string &filename) { ifstream file(filename.c_str()); string content((istreambuf_iterator(file)), @@ -494,15 +669,13 @@ class ServiceChainTest : public ::testing::Test { stringstream target; target << "target:64496:" << 100; - BGP_DEBUG_UT("ADD routing instance " << name << " Route Target " << target.str()); ifmap_test_util::IFMapMsgLink(&config_db_, "routing-instance", name, "route-target", target.str(), "instance-target"); - TASK_UTIL_EXPECT_NE(static_cast(NULL), - bgp_server_->routing_instance_mgr()->GetRoutingInstance(name)); - - BGP_DEBUG_UT("ADD connection " << name << "<->" << connection); + task_util::WaitForIdle(); + RoutingInstanceMgr *rim = bgp_server_->routing_instance_mgr(); + TASK_UTIL_EXPECT_TRUE(rim->GetRoutingInstance(name) != NULL); ifmap_test_util::IFMapMsgLink(&config_db_, "routing-instance", name, "routing-instance", connection, @@ -515,10 +688,7 @@ class ServiceChainTest : public ::testing::Test { "routing-instance", name, "routing-instance", connection, "connection"); - // - // Cache a copy of the export route-targets before the instance is - // deleted - // + // Cache copy of export route-targets before instance is deleted RoutingInstance *rti = bgp_server_->routing_instance_mgr()->GetRoutingInstance(name); const RoutingInstance::RouteTargetList @@ -529,6 +699,7 @@ class ServiceChainTest : public ::testing::Test { "route-target", tgt.ToString(), "instance-target"); } + task_util::WaitForIdle(); } void AddConnection(const string &instance1, const string &instance2) { @@ -539,11 +710,12 @@ class ServiceChainTest : public ::testing::Test { task_util::WaitForIdle(); } - std::auto_ptr - GetChainConfig(std::string filename) { - std::auto_ptr + auto_ptr + GetChainConfig(string filename) { + auto_ptr params (new autogen::ServiceChainInfo()); string content = FileRead(filename); + EXPECT_FALSE(content.empty()); istringstream sstream(content); xml_document xdoc; xml_parse_result result = xdoc.load(sstream); @@ -557,10 +729,24 @@ class ServiceChainTest : public ::testing::Test { return params; } - std::vector GetSGIDListFromRoute(const BgpPath *path) { + void SetServiceChainInformation(const string &instance, + const string &filename) { + auto_ptr params = GetChainConfig(filename); + ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", + instance, "service-chain-information", params.release(), 0); + task_util::WaitForIdle(); + } + + void ClearServiceChainInformation(const string &instance) { + ifmap_test_util::IFMapMsgPropertyDelete(&config_db_, "routing-instance", + instance, "service-chain-information"); + task_util::WaitForIdle(); + } + + vector GetSGIDListFromRoute(const BgpPath *path) { const ExtCommunity *ext_comm = path->GetAttr()->ext_community(); assert(ext_comm); - std::vector list; + vector list; BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm, ext_comm->communities()) { if (!ExtCommunity::is_security_group(comm)) @@ -569,14 +755,14 @@ class ServiceChainTest : public ::testing::Test { list.push_back(security_group.security_group_id()); } - std::sort(list.begin(), list.end()); + sort(list.begin(), list.end()); return list; } - std::set GetTunnelEncapListFromRoute(const BgpPath *path) { + set GetTunnelEncapListFromRoute(const BgpPath *path) { const ExtCommunity *ext_comm = path->GetAttr()->ext_community(); assert(ext_comm); - std::set list; + set list; BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm, ext_comm->communities()) { if (!ExtCommunity::is_tunnel_encap(comm)) @@ -588,7 +774,7 @@ class ServiceChainTest : public ::testing::Test { return list; } - std::string GetOriginVnFromRoute(const BgpPath *path) { + string GetOriginVnFromRoute(const BgpPath *path) { const ExtCommunity *ext_comm = path->GetAttr()->ext_community(); assert(ext_comm); BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm, @@ -602,7 +788,7 @@ class ServiceChainTest : public ::testing::Test { } static void ValidateShowServiceChainResponse(Sandesh *sandesh, - vector &result) { + vector &result) { ShowServiceChainResp *resp = dynamic_cast(sandesh); TASK_UTIL_EXPECT_NE((ShowServiceChainResp *)NULL, resp); @@ -622,7 +808,7 @@ class ServiceChainTest : public ::testing::Test { } static void ValidateShowPendingServiceChainResponse(Sandesh *sandesh, - vector &result) { + vector &result) { ShowPendingServiceChainResp *resp = dynamic_cast(sandesh); TASK_UTIL_EXPECT_NE((ShowPendingServiceChainResp *)NULL, resp); @@ -633,7 +819,7 @@ class ServiceChainTest : public ::testing::Test { } - void VerifyServiceChainSandesh(std::vector result) { + void VerifyServiceChainSandesh(vector result) { BgpSandeshContext sandesh_context; sandesh_context.bgp_server = bgp_server_.get(); sandesh_context.xmpp_peer_manager = NULL; @@ -647,7 +833,7 @@ class ServiceChainTest : public ::testing::Test { TASK_UTIL_EXPECT_EQ(1, validate_done_); } - void VerifyPendingServiceChainSandesh(std::vector pending) { + void VerifyPendingServiceChainSandesh(vector pending) { BgpSandeshContext sandesh_context; sandesh_context.bgp_server = bgp_server_.get(); sandesh_context.xmpp_peer_manager = NULL; @@ -700,49 +886,27 @@ TEST_P(ServiceChainParamTest, Basic) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, MoreSpecificAddDelete) { @@ -752,67 +916,43 @@ TEST_P(ServiceChainParamTest, MoreSpecificAddDelete) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add different more specific AddInetRoute(NULL, "red", "192.168.1.34/32", 100); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Add different more specific AddInetRoute(NULL, "red", "192.168.2.34/32", 100); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.2.34/32"); DeleteInetRoute(NULL, "red", "192.168.1.34/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ConnectedAddDelete) { @@ -822,49 +962,31 @@ TEST_P(ServiceChainParamTest, ConnectedAddDelete) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Delete connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } @@ -875,64 +997,38 @@ TEST_P(ServiceChainParamTest, DeleteConnected) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); - LOG(DEBUG, "XXXXXX -- Delete the connected route 1.1.2.3/32 --- XXXXXX"); // Delete connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); - LOG(DEBUG, "XXXXXX -- Add more specific route 192.168.2.1/32 --- XXXXXX"); AddInetRoute(NULL, "red", "192.168.2.1/32", 100); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); + VerifyInetRouteNoExists("blue", "192.168.2.0/24"); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); + // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteExists("blue", "192.168.2.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.2.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, StopServiceChain) { @@ -942,40 +1038,24 @@ TEST_P(ServiceChainParamTest, StopServiceChain) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); - ifmap_test_util::IFMapMsgPropertyDelete(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information"); - task_util::WaitForIdle(); + ClearServiceChainInformation("blue-i1"); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ServiceChainWithExistingRouteEntries) { @@ -995,43 +1075,19 @@ TEST_P(ServiceChainParamTest, ServiceChainWithExistingRouteEntries) { AddInetRoute(NULL, "red", "192.168.2.3/32", 100); AddInetRoute(NULL, "red", "192.168.2.4/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); - - // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteExists("blue", "192.168.2.0/24"); - ifmap_test_util::IFMapMsgPropertyDelete(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information"); - task_util::WaitForIdle(); - - // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + ClearServiceChainInformation("blue-i1"); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); @@ -1043,7 +1099,6 @@ TEST_P(ServiceChainParamTest, ServiceChainWithExistingRouteEntries) { DeleteInetRoute(NULL, "red", "192.168.2.3/32"); DeleteInetRoute(NULL, "red", "192.168.2.4/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, UpdateNexthop) { @@ -1053,63 +1108,26 @@ TEST_P(ServiceChainParamTest, UpdateNexthop) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & Connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "3.4.5.6"); - task_util::WaitForIdle(); - int count = 0; - while(1) { - // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - BgpAttrPtr attr = aggregate_path->GetAttr(); - if (attr->nexthop().to_v4().to_string() == "3.4.5.6") { - break; - } - if (count++ == 100) { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "3.4.5.6"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); - break; - } - } + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "3.4.5.6", "red"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } @@ -1120,57 +1138,26 @@ TEST_P(ServiceChainParamTest, UpdateLabel) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & Connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 16); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ(aggregate_path->GetLabel(), 16); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red", 16); // Add Connected with updated label AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 32); - task_util::WaitForIdle(); - int count = 0; - while(1) { - // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - if (aggregate_path->GetLabel() == 32) { - break; - } - if (count++ == 100) { - EXPECT_EQ(aggregate_path->GetLabel(), 32); - break; - } - } + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red", 32); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, DeleteRoutingInstance) { @@ -1180,34 +1167,21 @@ TEST_P(ServiceChainParamTest, DeleteRoutingInstance) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific & Connected AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); RemoveRoutingInstance("blue-i1", "blue"); - task_util::WaitForIdle(); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } @@ -1218,25 +1192,14 @@ TEST_P(ServiceChainParamTest, PendingChain) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); VerifyPendingServiceChainSandesh(list_of("blue-i1")); @@ -1250,14 +1213,11 @@ TEST_P(ServiceChainParamTest, PendingChain) { AddInetRoute(NULL, "red", "192.168.1.1/32", 100); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); // Delete More specific & connected DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, UnresolvedPendingChain) { @@ -1267,31 +1227,18 @@ TEST_P(ServiceChainParamTest, UnresolvedPendingChain) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); VerifyPendingServiceChainSandesh(list_of("blue-i1")); - ifmap_test_util::IFMapMsgPropertyDelete(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information"); - task_util::WaitForIdle(); + ClearServiceChainInformation("blue-i1"); // Delete connected DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, UpdateChain) { @@ -1301,54 +1248,28 @@ TEST_P(ServiceChainParamTest, UpdateChain) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_3.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_3.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); AddInetRoute(NULL, "red", "192.169.2.1/32", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.169.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteExists("blue", "192.169.2.0/24"); VerifyServiceChainSandesh(list_of("blue-i1")); - params = GetChainConfig("controller/src/bgp/testdata/service_chain_2.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_2.xml"); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.0.0/16"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.169.2.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.0.0/16"); + VerifyInetRouteExists("blue", "192.169.2.0/24"); VerifyServiceChainSandesh(list_of("blue-i1")); @@ -1356,7 +1277,6 @@ TEST_P(ServiceChainParamTest, UpdateChain) { DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.169.2.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, PeerUpdate) { @@ -1366,76 +1286,34 @@ TEST_P(ServiceChainParamTest, PeerUpdate) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.3", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 90, "2.3.0.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ(aggregate_rt->count(), 1); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.0.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.0.5", "red"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); - task_util::WaitForIdle(); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.1.5", BgpPath::PathIdString(aggregate_path->GetPathId())); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.1.5", "red"); AddConnectedRoute(peers_[2], "1.1.2.3/32", 95, "2.3.2.5"); - task_util::WaitForIdle(); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.1.5", BgpPath::PathIdString(aggregate_path->GetPathId())); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.1.5", "red"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.2.5", BgpPath::PathIdString(aggregate_path->GetPathId())); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.2.5", "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[2], "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -1456,107 +1334,46 @@ TEST_P(ServiceChainParamTest, DuplicateForwardingPaths) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Add Connected with duplicate forwarding information AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.4.5"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - EXPECT_EQ(aggregate_rt->count(), 1); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - EXPECT_EQ(ext_rt->count(), 1); - attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Delete connected route from peers_[0] DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - EXPECT_EQ(aggregate_rt->count(), 1); - attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - EXPECT_EQ(ext_rt->count(), 1); - attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete Ext connect route DeleteInetRoute(NULL, "red", "10.1.1.0/24"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, EcmpPaths) { @@ -1566,84 +1383,32 @@ TEST_P(ServiceChainParamTest, EcmpPaths) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - EXPECT_EQ(aggregate_rt->count(), 1); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.0.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.0.5", "red"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); - task_util::WaitForIdle(); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 2, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 2); - - std::string path_ids[] = {"2.3.0.5", "2.3.1.5"}; - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - BgpPath *path = static_cast(it.operator->()); - if (BgpPath::PathIdString(path->GetPathId()) == path_id) { - found = true; - break; - } - } - EXPECT_TRUE(found); - } + + vector path_ids = list_of("2.3.0.5")("2.3.1.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - ASSERT_TRUE(BgpPath::PathIdString(path->GetPathId()) != "2.3.1.5"); - } + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.0.5", "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, EcmpPathUpdate) { @@ -1653,68 +1418,22 @@ TEST_P(ServiceChainParamTest, EcmpPathUpdate) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 2, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 2); - - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - BgpAttrPtr attr = path->GetAttr(); - if (BgpPath::PathIdString(path->GetPathId()) == "2.3.0.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.0.5"); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.1.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.1.5"); - } - EXPECT_EQ(GetOriginVnFromRoute(path), "red"); - } - AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.8"); - task_util::WaitForIdle(); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + vector path_ids = list_of("2.3.0.5")("2.3.1.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 2, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 2); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - BgpAttrPtr attr = path->GetAttr(); - if (BgpPath::PathIdString(path->GetPathId()) == "2.3.0.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.0.5"); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.1.8") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.1.8"); - } - EXPECT_EQ(GetOriginVnFromRoute(path), "red"); - } + AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.8"); + path_ids = list_of("2.3.0.5")("2.3.1.8"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); @@ -1722,171 +1441,89 @@ TEST_P(ServiceChainParamTest, EcmpPathUpdate) { // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); } -TEST_P(ServiceChainParamTest, N_ECMP_PATHADD) { +TEST_P(ServiceChainParamTest, EcmpPathAdd) { vector instance_names = list_of("blue")("blue-i1")("red-i2")("red"); multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.3", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.4", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.0.5", "red"); - TaskScheduler *scheduler = TaskScheduler::GetInstance(); - scheduler->Stop(); + DisableServiceChainQ(); DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); AddConnectedRoute(peers_[2], "1.1.2.3/32", 100, "2.3.2.5"); AddConnectedRoute(peers_[3], "1.1.2.3/32", 100, "2.3.3.5"); - scheduler->Start(); - task_util::WaitForIdle(); + EnableServiceChainQ(); - // Check for aggregated route count - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 3, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 3); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - BgpAttrPtr attr = path->GetAttr(); - assert(path->GetPeer() != peers_[0]); - - if (BgpPath::PathIdString(path->GetPathId()) == "2.3.1.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.1.5"); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.2.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.2.5"); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.3.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.3.5"); - } - EXPECT_EQ(GetOriginVnFromRoute(path), "red"); - } + vector path_ids = list_of("2.3.1.5")("2.3.2.5")("2.3.3.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); - scheduler->Stop(); + DisableServiceChainQ(); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); DeleteConnectedRoute(peers_[2], "1.1.2.3/32"); DeleteConnectedRoute(peers_[3], "1.1.2.3/32"); AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", - BgpPath::AsPathLooped); - scheduler->Start(); - task_util::WaitForIdle(); + BgpPath::AsPathLooped); + EnableServiceChainQ(); // Check for aggregated route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); } -TEST_P(ServiceChainParamTest, N_ECMP_PATHDEL) { +TEST_P(ServiceChainParamTest, EcmpPathDelete) { vector instance_names = list_of("blue")("blue-i1")("red-i2")("red"); multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.3", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.4", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific - TaskScheduler *scheduler = TaskScheduler::GetInstance(); - scheduler->Stop(); + DisableServiceChainQ(); AddInetRoute(NULL, "red", "192.168.1.1/32", 100); AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); AddConnectedRoute(peers_[2], "1.1.2.3/32", 100, "2.3.2.5"); AddConnectedRoute(peers_[3], "1.1.2.3/32", 90, "2.3.3.5"); - scheduler->Start(); + EnableServiceChainQ(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + vector path_ids = list_of("2.3.0.5")("2.3.1.5")("2.3.2.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 3, 1000, 10000, - "Wait for Aggregate route in blue.."); - EXPECT_EQ(aggregate_rt->count(), 3); - - scheduler->Stop(); + DisableServiceChainQ(); DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); DeleteConnectedRoute(peers_[2], "1.1.2.3/32"); - scheduler->Start(); - task_util::WaitForIdle(); - - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 1, 1000, 10000, - "Wait for all paths in Aggregate route .."); + EnableServiceChainQ(); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.3.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - EXPECT_EQ(aggregate_rt->count(), 1); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.3.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.3.5", "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); // Delete connected route DeleteConnectedRoute(peers_[3], "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -1905,152 +1542,54 @@ TEST_P(ServiceChainParamTest, EcmpWithDuplicateForwardingPaths) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.3", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.4", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Add Connected with duplicate forwarding information F1 AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.4.5"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Add Connected with duplicate forwarding information F2 AddConnectedRoute(peers_[2], "1.1.2.3/32", 100, "2.3.4.6"); AddConnectedRoute(peers_[3], "1.1.2.3/32", 100, "2.3.4.6"); - task_util::WaitForIdle(); - - std::string path_ids[] = {"2.3.4.5", "2.3.4.6"}; // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 2); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *aggregate_path = static_cast(it.operator->()); - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - if (BgpPath::PathIdString(aggregate_path->GetPathId()) == path_id) { - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), path_id); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); - found = true; - break; - } - } - EXPECT_TRUE(found); - } + VerifyInetRouteExists("blue", "192.168.1.0/24"); + vector path_ids = list_of("2.3.4.5")("2.3.4.6"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - EXPECT_EQ(ext_rt->count(), 2); - for (Route::PathList::iterator it = ext_rt->GetPathList().begin(); - it != ext_rt->GetPathList().end(); it++) { - BgpPath *ext_path = static_cast(it.operator->()); - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - if (BgpPath::PathIdString(ext_path->GetPathId()) == path_id) { - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), path_id); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); - found = true; - break; - } - } - EXPECT_TRUE(found); - } + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", path_ids, "red"); // Delete connected routes from peers_[0] and peers_[2] DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[2], "1.1.2.3/32"); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 2); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *aggregate_path = static_cast(it.operator->()); - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - if (BgpPath::PathIdString(aggregate_path->GetPathId()) == path_id) { - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), path_id); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); - found = true; - break; - } - } - EXPECT_TRUE(found); - } + VerifyInetRouteExists("blue", "192.168.1.0/24"); + path_ids = list_of("2.3.4.5")("2.3.4.6"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - EXPECT_EQ(ext_rt->count(), 2); - for (Route::PathList::iterator it = ext_rt->GetPathList().begin(); - it != ext_rt->GetPathList().end(); it++) { - BgpPath *ext_path = static_cast(it.operator->()); - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - if (BgpPath::PathIdString(ext_path->GetPathId()) == path_id) { - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), path_id); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); - found = true; - break; - } - } - EXPECT_TRUE(found); - } + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", path_ids, "red"); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete Ext connect route DeleteInetRoute(NULL, "red", "10.1.1.0/24"); - task_util::WaitForIdle(); // Delete connected routes DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); DeleteConnectedRoute(peers_[3], "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2067,52 +1606,29 @@ TEST_P(ServiceChainParamTest, IgnoreAggregateRoute) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Add MX leaked route AddInetRoute(NULL, "red", "192.168.1.0/24", 100); - task_util::WaitForIdle(); // Check for absence of ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Delete MX leaked, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.0/24"); DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2132,86 +1648,53 @@ TEST_P(ServiceChainParamTest, ExtConnectRoute) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "10.1.1.0/24"); + // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + // Check for absence Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Delete Connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2231,61 +1714,35 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteNoAdvertiseCommunity) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.0/24"); // Change Ext connect route to have NO_ADVERTISE community - std::vector commlist = list_of(Community::NoAdvertise); + vector commlist = list_of(Community::NoAdvertise); AddInetRoute(NULL, "red", "10.1.1.0/24", 100, commlist); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "10.1.1.0/24"); // Change Ext connect route to not have NO_ADVERTISE community AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Delete ExtRoute and connected route DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2306,62 +1763,37 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteOriginVnOnly) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Add route to green VN which gets imported into red AddInetRoute(NULL, "green", "20.1.1.0/24", 100); - task_util::WaitForIdle(); // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - // Verify ExtConnect route attributes - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Check for non-OriginVn route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "20.1.1.0/24"), - NULL, 1000, 10000, - "Wait for non-origin vn route in blue.."); + VerifyInetRouteNoExists("blue", "20.1.1.0/24"); // Delete ExtRoute, More specific, non-OriginVn and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteInetRoute(NULL, "green", "20.1.1.0/24"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2382,49 +1814,26 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteOriginVnUnresolved1) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Add Ext connect route with targets of both red and green. vector instances = list_of("red")("green"); AddInetVpnRoute(NULL, instances, "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Verify that MX leaked route is present in red - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("red", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for MX leaked route in red.."); + VerifyInetRouteExists("red", "10.1.1.0/24"); // Verify that ExtConnect route is present in blue - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - // Verify ExtConnect route attributes - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red"); // Delete ExtRoute and connected route DeleteInetVpnRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2445,40 +1854,25 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteOriginVnUnresolved2) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Add Ext connect route with targets of green and yellow. vector instances = list_of("green")("yellow"); AddInetVpnRoute(NULL, instances, "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Verify that MX leaked route is present in red - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("red", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for MX leaked route in red.."); + VerifyInetRouteExists("red", "10.1.1.0/24"); // Verify that ExtConnect route is not present in blue - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "10.1.1.0/24"); // Delete ExtRoute and connected route DeleteInetVpnRoute(NULL, "green", "10.1.1.0/24"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2495,59 +1889,34 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteCoveringSubnetPrefix) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route.. Say MX leaks /16 route AddInetRoute(NULL, "red", "192.168.0.0/16", 100); - task_util::WaitForIdle(); AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.0.0/16"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.0.0/16"); // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.0.0/16"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "192.168.0.0/16"); + VerifyInetRouteAttributes("blue", "192.168.0.0/16", "2.3.4.5", "red"); + // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "192.168.0.0/16"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.4.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.0.0/16"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2564,51 +1933,34 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteWithinSubnetPrefix) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route.. Say MX leaks /30 route AddInetRoute(NULL, "red", "192.168.1.252/30", 100); - task_util::WaitForIdle(); AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.252/30"); + // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.252/30"); + // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.4.5", "red"); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.1.252/30"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } // @@ -2639,127 +1991,75 @@ TEST_P(ServiceChainParamTest, ExtConnectRouteServiceChainUpdate) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route.. Say MX leaks /30 route AddInetRoute(NULL, "red", "192.168.1.252/30", 100); - task_util::WaitForIdle(); AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.252/30"); + // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.252/30"); + // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - - params = GetChainConfig("controller/src/bgp/testdata/service_chain_4.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_4.xml"); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.1/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.252/30"); + VerifyInetRouteExists("blue", "192.168.1.1/32"); + // Check for Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "10.1.1.0/24"); + // Check for Previous Aggregate route - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); // Add Ext connect route.. Say MX leaks /16 route AddInetRoute(NULL, "red", "192.168.0.0/16", 100); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.0.0/16"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "192.168.0.0/16"); // Add more specific for new subnet prefix AddInetRoute(NULL, "red", "10.1.1.1/32", 100); - task_util::WaitForIdle(); // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - - params = GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Check for ext connect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.1/32"), - NULL, 1000, 10000, - "Wait for Ext connect route in blue.."); - // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.0.0/16"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.1/32"); + VerifyInetRouteExists("blue", "192.168.0.0/16"), + // Check for new Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + // Check for removal of ExtConnect route it is now more specific - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.252/30"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.252/30"); + // Check for removal of ExtConnect route it is now more specific - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.1/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.1.252/30"); DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.0.0/16"); DeleteInetRoute(NULL, "red", "10.1.1.1/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ExtConnectedEcmpPaths) { @@ -2769,79 +2069,32 @@ TEST_P(ServiceChainParamTest, ExtConnectedEcmpPaths) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add MX leaked route AddInetRoute(NULL, "red", "10.10.1.0/24", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); - task_util::WaitForIdle(); // Check for external connected route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.10.1.0/24"), - NULL, 1000, 10000, - "Wait for External connecting route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.10.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(ext_path->GetPathId())); - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.0.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.10.1.0/24"); + VerifyInetRouteAttributes("blue", "10.10.1.0/24", "2.3.0.5", "red"); + // Add Connected AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); - task_util::WaitForIdle(); - - ext_rt = InetRouteLookup("blue", "10.10.1.0/24"); - std::string path_ids[] = {"2.3.0.5", "2.3.1.5"}; - for (Route::PathList::iterator it = ext_rt->GetPathList().begin(); - it != ext_rt->GetPathList().end(); it++) { - bool found = false; - BOOST_FOREACH(std::string path_id, path_ids) { - BgpPath *path = static_cast(it.operator->()); - if (BgpPath::PathIdString(path->GetPathId()) == path_id) { - found = true; - break; - } - } - EXPECT_TRUE(found); - } + vector path_ids = list_of("2.3.0.5")("2.3.1.5"); + VerifyInetRouteAttributes("blue", "10.10.1.0/24", path_ids, "red"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); + VerifyInetRouteAttributes("blue", "10.10.1.0/24", "2.3.0.5", "red"); - ext_rt = InetRouteLookup("blue", "10.10.1.0/24"); - for (Route::PathList::iterator it = ext_rt->GetPathList().begin(); - it != ext_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - ASSERT_TRUE(BgpPath::PathIdString(path->GetPathId()) != "2.3.1.5"); - } - // Delete MX route DeleteInetRoute(NULL, "red", "10.10.1.0/24"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); } @@ -2852,108 +2105,57 @@ TEST_P(ServiceChainParamTest, ExtConnectedMoreSpecificEcmpPaths) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); - task_util::WaitForIdle(); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100); - task_util::WaitForIdle(); // Check for Aggregate route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.0.5", "red"); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - EXPECT_EQ(ext_rt->count(), 1); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(ext_path->GetPathId())); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.0.5", "red"); // Connected path is infeasible AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", - BgpPath::AsPathLooped); - task_util::WaitForIdle(); + BgpPath::AsPathLooped); // Verify that Aggregate route and ExtConnect route is gone - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "192.168.1.0/24"); + VerifyInetRouteNoExists("blue", "10.1.1.0/24"); // Connected path again from two peers AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5"); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.1.5"); - task_util::WaitForIdle(); // Check for Aggregate & ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate connect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 2, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 2); - TASK_UTIL_WAIT_EQ_NO_MSG(ext_rt->count(), 2, 1000, 10000, - "Wait for all paths in Service Chain route .."); - EXPECT_EQ(ext_rt->count(), 2); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + vector path_ids = list_of("2.3.0.5")("2.3.1.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", path_ids, "red"); // Connected path is infeasible AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", - BgpPath::AsPathLooped); - task_util::WaitForIdle(); + BgpPath::AsPathLooped); - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 1); - EXPECT_EQ(ext_rt->count(), 1); - aggregate_path = aggregate_rt->BestPath(); - EXPECT_EQ("2.3.1.5", BgpPath::PathIdString(aggregate_path->GetPathId())); - ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.1.5", BgpPath::PathIdString(ext_path->GetPathId())); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", "2.3.1.5", "red"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.1.5", "red"); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ServiceChainRouteSGID) { @@ -2964,105 +2166,46 @@ TEST_P(ServiceChainParamTest, ServiceChainRouteSGID) { VerifyNetworkConfig(instance_names); bgp_server_->service_chain_mgr()->set_aggregate_host_route(false); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); - std::vector sgid_list_more_specific_1 = list_of(1)(2)(3)(4); - std::vector sgid_list_more_specific_2 = list_of(5)(6)(7)(8); - std::vector sgid_list_connected = list_of(9)(10)(11)(12); - std::vector sgid_list_ext = list_of(13)(14)(15)(16); + vector sgid_list_more_specific_1 = list_of(1)(2)(3)(4); + vector sgid_list_more_specific_2 = list_of(5)(6)(7)(8); + vector sgid_list_connected = list_of(9)(10)(11)(12); + vector sgid_list_ext = list_of(13)(14)(15)(16); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100, vector(), sgid_list_ext); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", 0, 0, sgid_list_connected); - task_util::WaitForIdle(); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100, vector(), sgid_list_more_specific_1); - task_util::WaitForIdle(); - AddInetRoute(NULL, "red", "192.168.1.2/32", 100, vector(), sgid_list_more_specific_2); - task_util::WaitForIdle(); - // Check for More specific routes leaked in src rtinstance - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.1/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.2/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); + // Check for More specific routes leaked in src instance + VerifyInetRouteExists("blue", "192.168.1.1/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.1/32", "2.3.0.5", "red", sgid_list_more_specific_1); + VerifyInetRouteExists("blue", "192.168.1.2/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.2/32", "2.3.0.5", "red", sgid_list_more_specific_2); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - BgpRoute *leak_rt_1 = InetRouteLookup("blue", "192.168.1.1/32"); - BgpRoute *leak_rt_2 = InetRouteLookup("blue", "192.168.1.2/32"); - - EXPECT_EQ(leak_rt_1->count(), 1); - EXPECT_EQ(leak_rt_2->count(), 1); - EXPECT_EQ(ext_rt->count(), 1); - - const BgpPath *leak_path = leak_rt_1->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(leak_path->GetPathId())); - std::vector list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_more_specific_1.begin(); - it1 != list.end() && it2 != sgid_list_more_specific_1.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - leak_path = leak_rt_2->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(leak_path->GetPathId())); - list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_more_specific_2.begin(); - it1 != list.end() && it2 != sgid_list_more_specific_2.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(ext_path->GetPathId())); - list = GetSGIDListFromRoute(ext_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_ext.begin(); - it1 != list.end() && it2 != sgid_list_ext.end(); it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes( + "blue", "10.1.1.0/24", "2.3.0.5", "red", sgid_list_ext); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.1.2/32"); DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ServiceChainRouteUpdateSGID) { @@ -3073,174 +2216,73 @@ TEST_P(ServiceChainParamTest, ServiceChainRouteUpdateSGID) { VerifyNetworkConfig(instance_names); bgp_server_->service_chain_mgr()->set_aggregate_host_route(false); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); - std::vector sgid_list_more_specific_1 = list_of(1)(2)(3)(4); - std::vector sgid_list_more_specific_2 = list_of(5)(6)(7)(8); - std::vector sgid_list_connected = list_of(9)(10)(11)(12); - std::vector sgid_list_ext = list_of(13)(14)(15)(16); + vector sgid_list_more_specific_1 = list_of(1)(2)(3)(4); + vector sgid_list_more_specific_2 = list_of(5)(6)(7)(8); + vector sgid_list_connected = list_of(9)(10)(11)(12); + vector sgid_list_ext = list_of(13)(14)(15)(16); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.0/24", 100, vector(), sgid_list_ext); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", 0, 0, sgid_list_connected); - task_util::WaitForIdle(); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100, vector(), sgid_list_more_specific_1); - task_util::WaitForIdle(); - AddInetRoute(NULL, "red", "192.168.1.2/32", 100, vector(), sgid_list_more_specific_2); - task_util::WaitForIdle(); - // Check for More specific routes leaked in src rtinstance - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.1/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.2/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); + // Check for More specific routes leaked in src instance + VerifyInetRouteExists("blue", "192.168.1.1/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.1/32", "2.3.0.5", "red", sgid_list_more_specific_1); + VerifyInetRouteExists("blue", "192.168.1.2/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.2/32", "2.3.0.5", "red", sgid_list_more_specific_2); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - BgpRoute *leak_rt_1 = InetRouteLookup("blue", "192.168.1.1/32"); - BgpRoute *leak_rt_2 = InetRouteLookup("blue", "192.168.1.2/32"); - - EXPECT_EQ(leak_rt_1->count(), 1); - EXPECT_EQ(leak_rt_2->count(), 1); - EXPECT_EQ(ext_rt->count(), 1); - - const BgpPath *leak_path = leak_rt_1->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(leak_path->GetPathId())); - std::vector list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_more_specific_1.begin(); - it1 != list.end() && it2 != sgid_list_more_specific_1.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - leak_path = leak_rt_2->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(leak_path->GetPathId())); - list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_more_specific_2.begin(); - it1 != list.end() && it2 != sgid_list_more_specific_2.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - const BgpPath *ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(ext_path->GetPathId())); - list = GetSGIDListFromRoute(ext_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_ext.begin(); - it1 != list.end() && it2 != sgid_list_ext.end(); it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes( + "blue", "10.1.1.0/24", "2.3.0.5", "red", sgid_list_ext); // Update Ext connect route with different SGID list AddInetRoute(NULL, "red", "10.1.1.0/24", 100, vector(), sgid_list_more_specific_1); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.0.5", 0, 0, sgid_list_more_specific_2); - task_util::WaitForIdle(); // Add more specific AddInetRoute(NULL, "red", "192.168.1.1/32", 100, vector(), sgid_list_ext); - task_util::WaitForIdle(); - AddInetRoute(NULL, "red", "192.168.1.2/32", 100, vector(), sgid_list_connected); - task_util::WaitForIdle(); // Check for More specific routes leaked in src rtinstance - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.1/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.2/32"), - NULL, 1000, 10000, - "Wait for route in blue.."); + VerifyInetRouteExists("blue", "192.168.1.1/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.1/32", "2.3.0.5", "red", sgid_list_ext); + VerifyInetRouteExists("blue", "192.168.1.2/32"); + VerifyInetRouteAttributes( + "blue", "192.168.1.2/32", "2.3.0.5", "red", sgid_list_connected); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - leak_rt_1 = InetRouteLookup("blue", "192.168.1.1/32"); - leak_rt_2 = InetRouteLookup("blue", "192.168.1.2/32"); - - EXPECT_EQ(leak_rt_1->count(), 1); - EXPECT_EQ(leak_rt_2->count(), 1); - EXPECT_EQ(ext_rt->count(), 1); - - leak_path = leak_rt_1->BestPath(); - list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_ext.begin(); - it1 != list.end() && it2 != sgid_list_ext.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - leak_path = leak_rt_2->BestPath(); - list = GetSGIDListFromRoute(leak_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_connected.begin(); - it1 != list.end() && it2 != sgid_list_connected.end(); - it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(leak_path), "red"); - - ext_path = ext_rt->BestPath(); - EXPECT_EQ("2.3.0.5", BgpPath::PathIdString(ext_path->GetPathId())); - list = GetSGIDListFromRoute(ext_path); - EXPECT_EQ(list.size(), 4); - for(std::vector::iterator it1 = list.begin(), - it2=sgid_list_more_specific_1.begin(); - it1 != list.end() && it2 != sgid_list_more_specific_1.end(); it1++, it2++) - EXPECT_EQ(*it1, *it2); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes( + "blue", "10.1.1.0/24", "2.3.0.5", "red", sgid_list_more_specific_1); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "192.168.1.1/32"); DeleteInetRoute(NULL, "red", "192.168.1.2/32"); DeleteInetRoute(NULL, "red", "10.1.1.0/24"); DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ValidateTunnelEncapAggregate) { @@ -3250,72 +2292,39 @@ TEST_P(ServiceChainParamTest, ValidateTunnelEncapAggregate) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); - set encap_more_specific = list_of("udp"); // Add More specific + set encap_more_specific = list_of("udp"); AddInetRoute(NULL, "red", "192.168.1.1/32", 100, vector(), vector(), encap_more_specific); - task_util::WaitForIdle(); - set encap = list_of("vxlan"); // Add Connected + set encap = list_of("vxlan"); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 0, vector(), encap); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - const BgpPath *aggregate_path = aggregate_rt->BestPath(); - set list = GetTunnelEncapListFromRoute(aggregate_path); - EXPECT_EQ(list, encap); - - BgpAttrPtr attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes( + "blue", "192.168.1.0/24", "2.3.4.5", "red", encap); - encap = list_of("gre"); // Add Connected + encap = list_of("gre"); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 0, vector(), encap); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - TASK_UTIL_EXPECT_TRUE(aggregate_rt->BestPath() != NULL); - aggregate_path = aggregate_rt->BestPath(); - list = GetTunnelEncapListFromRoute(aggregate_path); - EXPECT_EQ(list, encap); - - attr = aggregate_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(aggregate_path), "red"); + VerifyInetRouteExists("blue", "192.168.1.0/24"); + VerifyInetRouteAttributes( + "blue", "192.168.1.0/24", "2.3.4.5", "red", encap); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, ValidateTunnelEncapExtRoute) { @@ -3325,72 +2334,37 @@ TEST_P(ServiceChainParamTest, ValidateTunnelEncapExtRoute) { NetworkConfig(instance_names, connections); VerifyNetworkConfig(instance_names); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route set encap_ext = list_of("vxlan"); AddInetRoute(NULL, "red", "10.1.1.0/24", 100, vector(), vector(), encap_ext); - task_util::WaitForIdle(); // Add Connected set encap = list_of("gre"); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 0, vector(), encap); - task_util::WaitForIdle(); // Check for service Chain router - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Service Chain route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.0/24"); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red", encap); - BgpRoute *ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - const BgpPath *ext_path = ext_rt->BestPath(); - set list = GetTunnelEncapListFromRoute(ext_path); - EXPECT_EQ(list, encap); - - BgpAttrPtr attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); - - encap = list_of("udp"); // Add Connected + encap = list_of("udp"); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5", 0, 0, vector(), encap); - task_util::WaitForIdle(); + VerifyInetRouteAttributes("blue", "10.1.1.0/24", "2.3.4.5", "red", encap); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.0/24"), - NULL, 1000, 10000, - "Wait for Service Chain route in blue.."); - - ext_rt = InetRouteLookup("blue", "10.1.1.0/24"); - TASK_UTIL_EXPECT_TRUE(ext_rt->BestPath() != NULL); - ext_path = ext_rt->BestPath(); - list = GetTunnelEncapListFromRoute(ext_path); - EXPECT_EQ(list, encap); - - attr = ext_path->GetAttr(); - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.4.5"); - EXPECT_EQ(GetOriginVnFromRoute(ext_path), "red"); + VerifyInetRouteExists("blue", "10.1.1.0/24"); // Delete ext connected route DeleteInetRoute(NULL, "red", "10.1.1.0/24"); - task_util::WaitForIdle(); // Delete connected route DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, MultiPathTunnelEncap) { @@ -3398,28 +2372,9 @@ TEST_P(ServiceChainParamTest, MultiPathTunnelEncap) { multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); - task_util::WaitForIdle(); - boost::system::error_code ec; - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.2", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.3", ec))); - peers_.push_back( - new BgpPeerMock(Ip4Address::from_string("192.168.0.4", ec))); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add More specific set encap_1 = list_of("gre"); @@ -3429,119 +2384,70 @@ TEST_P(ServiceChainParamTest, MultiPathTunnelEncap) { AddConnectedRoute(peers_[0], "1.1.2.3/32", 100, "2.3.1.5", 0, 0, vector(), encap_1); AddConnectedRoute(peers_[1], "1.1.2.3/32", 100, "2.3.2.5", 0, 0, vector(), encap_2); AddConnectedRoute(peers_[2], "1.1.2.3/32", 100, "2.3.3.5", 0, 0, vector(), encap_3); - task_util::WaitForIdle(); // Check for aggregated route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "192.168.1.0/24"), - NULL, 1000, 10000, - "Wait for Aggregate route in blue.."); - - BgpRoute *aggregate_rt = InetRouteLookup("blue", "192.168.1.0/24"); - EXPECT_EQ(aggregate_rt->count(), 3); - - // Check for aggregated route count - TASK_UTIL_WAIT_EQ_NO_MSG(aggregate_rt->count(), 3, 1000, 10000, - "Wait for all paths in Aggregate route .."); - EXPECT_EQ(aggregate_rt->count(), 3); - for (Route::PathList::iterator it = aggregate_rt->GetPathList().begin(); - it != aggregate_rt->GetPathList().end(); it++) { - BgpPath *path = static_cast(it.operator->()); - set list = GetTunnelEncapListFromRoute(path); - BgpAttrPtr attr = path->GetAttr(); - if (BgpPath::PathIdString(path->GetPathId()) == "2.3.1.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.1.5"); - EXPECT_EQ(list, encap_1); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.2.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.2.5"); - EXPECT_EQ(list, encap_2); - } else if (BgpPath::PathIdString(path->GetPathId()) == "2.3.3.5") { - EXPECT_EQ(attr->nexthop().to_v4().to_string(), "2.3.3.5"); - EXPECT_EQ(list, encap_3); - } - EXPECT_EQ(GetOriginVnFromRoute(path), "red"); - } + VerifyInetRouteExists("blue", "192.168.1.0/24"); + vector path_ids = list_of("2.3.1.5")("2.3.2.5")("2.3.3.5"); + VerifyInetRouteAttributes("blue", "192.168.1.0/24", path_ids, "red"); + VerifyInetPathAttributes( + "blue", "192.168.1.0/24", "2.3.1.5", "red", encap_1); + VerifyInetPathAttributes( + "blue", "192.168.1.0/24", "2.3.2.5", "red", encap_2); + VerifyInetPathAttributes( + "blue", "192.168.1.0/24", "2.3.3.5", "red", encap_3); // Delete More specific DeleteInetRoute(NULL, "red", "192.168.1.1/32"); + // Delete connected route DeleteConnectedRoute(peers_[0], "1.1.2.3/32"); DeleteConnectedRoute(peers_[1], "1.1.2.3/32"); DeleteConnectedRoute(peers_[2], "1.1.2.3/32"); - task_util::WaitForIdle(); } - TEST_P(ServiceChainParamTest, DeleteConnectedWithExtConnectRoute) { vector instance_names = list_of("blue")("blue-i1")("red-i2")("red"); multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); - task_util::WaitForIdle(); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); // Add Ext connect route AddInetRoute(NULL, "red", "10.1.1.1/32", 100); AddInetRoute(NULL, "red", "10.1.1.2/32", 100); AddInetRoute(NULL, "red", "10.1.1.3/32", 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.1/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.2/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.3/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.1/32"); + VerifyInetRouteExists("blue", "10.1.1.2/32"); + VerifyInetRouteExists("blue", "10.1.1.3/32"); DisableServiceChainQ(); AddConnectedRoute(NULL, "1.1.2.3/32", 200, "2.3.4.5"); DeleteInetRoute(NULL, "red", "10.1.1.1/32"); - BgpRoute *ext_rt = InetRouteLookup("red", "10.1.1.1/32"); - TASK_UTIL_WAIT_EQ_NO_MSG(ext_rt->IsDeleted(), - true, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteIsDeleted("red", "10.1.1.1/32"); + // Check for ExtConnect route - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.1/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.2/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", "10.1.1.3/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", "10.1.1.1/32"); + VerifyInetRouteExists("blue", "10.1.1.2/32"); + VerifyInetRouteExists("blue", "10.1.1.3/32"); EnableServiceChainQ(); TASK_UTIL_EXPECT_TRUE(bgp_server_->service_chain_mgr()->IsQueueEmpty()); - TASK_UTIL_WAIT_EQ_NO_MSG(InetRouteLookup("blue", "10.1.1.1/32"), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteNoExists("blue", "10.1.1.1/32"); // Delete ExtRoute, More specific and connected route DeleteInetRoute(NULL, "red", "10.1.1.2/32"); DeleteInetRoute(NULL, "red", "10.1.1.3/32"); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, DeleteEntryReuse) { @@ -3549,74 +2455,54 @@ TEST_P(ServiceChainParamTest, DeleteEntryReuse) { multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); - task_util::WaitForIdle(); - - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); - std::vector routes_to_play = list_of("10.1.1.1/32")("10.1.1.2/32")("10.1.1.3/32"); + vector routes_to_play = + list_of("10.1.1.1/32")("10.1.1.2/32")("10.1.1.3/32"); // Add Ext connect route - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) AddInetRoute(NULL, "red", *it, 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) { - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", *it), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", *it); } DisableServiceChainQ(); - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) DeleteInetRoute(NULL, "red", *it); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) { - BgpRoute *ext_rt = InetRouteLookup("red", *it); - TASK_UTIL_WAIT_EQ_NO_MSG(ext_rt->IsDeleted(), - true, 1000, 10000, - "Wait for delete marking of ExtConnect route in red.."); + VerifyInetRouteIsDeleted("red", *it); } - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) AddInetRoute(NULL, "red", *it, 100); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) DeleteInetRoute(NULL, "red", *it); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) { - BgpRoute *ext_rt = InetRouteLookup("red", *it); - TASK_UTIL_WAIT_EQ_NO_MSG(ext_rt->IsDeleted(), - true, 1000, 10000, - "Wait for delete marking of ExtConnect route in red.."); + VerifyInetRouteIsDeleted("red", *it); } EnableServiceChainQ(); TASK_UTIL_EXPECT_TRUE(bgp_server_->service_chain_mgr()->IsQueueEmpty()); - - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, EntryAfterStop) { @@ -3624,20 +2510,11 @@ TEST_P(ServiceChainParamTest, EntryAfterStop) { multimap connections = map_list_of("blue", "blue-i1") ("red-i2", "red"); NetworkConfig(instance_names, connections); - task_util::WaitForIdle(); - std::auto_ptr params = - GetChainConfig("controller/src/bgp/testdata/service_chain_1.xml"); + SetServiceChainInformation("blue-i1", + "controller/src/bgp/testdata/service_chain_1.xml"); - // Service Chain Info - ifmap_test_util::IFMapMsgPropertyAdd(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information", - params.release(), - 0); - task_util::WaitForIdle(); - - std::vector routes_to_play; + vector routes_to_play; // Add Ext connect route for (int i = 0; i < 255; i++) { stringstream route; @@ -3645,27 +2522,22 @@ TEST_P(ServiceChainParamTest, EntryAfterStop) { routes_to_play.push_back(route.str()); } - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) AddInetRoute(NULL, "red", *it, 100); - task_util::WaitForIdle(); // Add Connected AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); - task_util::WaitForIdle(); // Check for ExtConnect route - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) { - TASK_UTIL_WAIT_NE_NO_MSG(InetRouteLookup("blue", *it), - NULL, 1000, 10000, - "Wait for ExtConnect route in blue.."); + VerifyInetRouteExists("blue", *it); } DisableServiceChainQ(); - ifmap_test_util::IFMapMsgPropertyDelete(&config_db_, "routing-instance", - "blue-i1", - "service-chain-information"); + ClearServiceChainInformation("blue-i1"); + // Add more Ext connect route for (int i = 0; i < 255; i++) { stringstream route; @@ -3673,7 +2545,7 @@ TEST_P(ServiceChainParamTest, EntryAfterStop) { routes_to_play.push_back(route.str()); } - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) AddInetRoute(NULL, "red", *it, 200); AddConnectedRoute(NULL, "1.1.2.3/32", 100, "2.3.4.5"); @@ -3681,34 +2553,26 @@ TEST_P(ServiceChainParamTest, EntryAfterStop) { EnableServiceChainQ(); TASK_UTIL_EXPECT_TRUE(bgp_server_->service_chain_mgr()->IsQueueEmpty()); - for (std::vector::iterator it = routes_to_play.begin(); + for (vector::iterator it = routes_to_play.begin(); it != routes_to_play.end(); it++) DeleteInetRoute(NULL, "red", *it); DeleteConnectedRoute(NULL, "1.1.2.3/32"); - TASK_UTIL_WAIT_EQ_NO_MSG(RouteCount("red"), - 0, 1000, 10000, - "Wait for route in red to be deleted.."); - task_util::WaitForIdle(); + TASK_UTIL_EXPECT_EQ(0, RouteCount("red")); } // // Instances are (blue)(blue-i1)(core-i2)(core)(core-i3)(red-i4)(red) // TEST_P(ServiceChainParamTest, TransitNetworkRemoteVMRoutes) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add more specific routes to red AddInetRoute(NULL, "red", "192.168.3.101/32", 100); AddInetRoute(NULL, "red", "192.168.3.102/32", 100); AddInetRoute(NULL, "red", "192.168.3.103/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 2 chains AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3724,26 +2588,20 @@ TEST_P(ServiceChainParamTest, TransitNetworkRemoteVMRoutes) { DeleteInetRoute(NULL, "red", "192.168.3.103/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); - task_util::WaitForIdle(); } // // Instances are (blue)(blue-i1)(core-i2)(core)(core-i3)(red-i4)(red) // TEST_P(ServiceChainParamTest, TransitNetworkLocalVMRoutes) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add more specific routes to core AddInetRoute(NULL, "core", "192.168.2.101/32", 100); AddInetRoute(NULL, "core", "192.168.2.102/32", 100); AddInetRoute(NULL, "core", "192.168.2.103/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the blue-core chain AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3757,26 +2615,20 @@ TEST_P(ServiceChainParamTest, TransitNetworkLocalVMRoutes) { DeleteInetRoute(NULL, "core", "192.168.2.102/32"); DeleteInetRoute(NULL, "core", "192.168.2.103/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); - task_util::WaitForIdle(); } // // Instances are (blue)(blue-i1)(core-i2)(core)(core-i3)(red-i4)(red) // TEST_P(ServiceChainParamTest, TransitNetworkRemoteExtConnectRoute) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add Ext connect routes to red AddInetRoute(NULL, "red", "10.1.3.1/32", 100); AddInetRoute(NULL, "red", "10.1.3.2/32", 100); AddInetRoute(NULL, "red", "10.1.3.3/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 2 chains. AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3797,23 +2649,17 @@ TEST_P(ServiceChainParamTest, TransitNetworkRemoteExtConnectRoute) { DeleteInetRoute(NULL, "red", "10.1.3.3/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); - task_util::WaitForIdle(); } TEST_P(ServiceChainParamTest, TransitNetworkLocalExtConnectRoute) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add Ext connect routes to core AddInetRoute(NULL, "core", "10.1.2.1/32", 100); AddInetRoute(NULL, "core", "10.1.2.2/32", 100); AddInetRoute(NULL, "core", "10.1.2.3/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the blue-core chain AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3832,30 +2678,23 @@ TEST_P(ServiceChainParamTest, TransitNetworkLocalExtConnectRoute) { DeleteInetRoute(NULL, "core", "10.1.2.2/32"); DeleteInetRoute(NULL, "core", "10.1.2.3/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); - task_util::WaitForIdle(); } // // Instances are (blue)(blue-i1)(core-i2)(core)(core-i3)(red-i4)(red) // TEST_P(ServiceChainParamTest, TransitNetworkAddDeleteConnectedRoute1) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add more specific routes to red AddInetRoute(NULL, "red", "192.168.3.101/32", 100); AddInetRoute(NULL, "red", "192.168.3.102/32", 100); - task_util::WaitForIdle(); // Add Ext connect routes to red AddInetRoute(NULL, "red", "10.1.3.1/32", 100); AddInetRoute(NULL, "red", "10.1.3.2/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 2 chains AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3903,30 +2742,23 @@ TEST_P(ServiceChainParamTest, TransitNetworkAddDeleteConnectedRoute1) { DeleteInetRoute(NULL, "red", "10.1.3.2/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); - task_util::WaitForIdle(); } // // Instances are (blue)(blue-i1)(core-i2)(core)(core-i3)(red-i4)(red) // TEST_P(ServiceChainParamTest, TransitNetworkAddDeleteConnectedRoute2) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add more specific routes to red AddInetRoute(NULL, "red", "192.168.3.101/32", 100); AddInetRoute(NULL, "red", "192.168.3.102/32", 100); - task_util::WaitForIdle(); // Add Ext connect routes to red AddInetRoute(NULL, "red", "10.1.3.1/32", 100); AddInetRoute(NULL, "red", "10.1.3.2/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 2 chains AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -3974,7 +2806,6 @@ TEST_P(ServiceChainParamTest, TransitNetworkAddDeleteConnectedRoute2) { DeleteInetRoute(NULL, "red", "10.1.3.2/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); - task_util::WaitForIdle(); } // @@ -3982,22 +2813,17 @@ TEST_P(ServiceChainParamTest, TransitNetworkAddDeleteConnectedRoute2) { // TEST_P(ServiceChainParamTest, TransitNetworkToggleAllowTransit) { string content = - FileRead("controller/src/bgp/testdata/service_chain_test_1.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_1.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); - task_util::WaitForIdle(); // Add more specific routes to red AddInetRoute(NULL, "red", "192.168.3.101/32", 100); AddInetRoute(NULL, "red", "192.168.3.102/32", 100); - task_util::WaitForIdle(); // Add Ext connect routes to red AddInetRoute(NULL, "red", "10.1.3.1/32", 100); AddInetRoute(NULL, "red", "10.1.3.2/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 2 chains AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -4019,8 +2845,7 @@ TEST_P(ServiceChainParamTest, TransitNetworkToggleAllowTransit) { boost::replace_all(content, "true", "false"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigString(content); // Check for Aggregate route in blue VerifyInetRouteNoExists("blue", "192.168.3.0/24"); @@ -4033,8 +2858,7 @@ TEST_P(ServiceChainParamTest, TransitNetworkToggleAllowTransit) { boost::replace_all(content, "false", "true"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigString(content); // Check for Aggregate route in blue aggregate_rt = VerifyInetRouteExists("blue", "192.168.3.0/24"); @@ -4053,7 +2877,6 @@ TEST_P(ServiceChainParamTest, TransitNetworkToggleAllowTransit) { DeleteInetRoute(NULL, "red", "10.1.3.2/32"); DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); - task_util::WaitForIdle(); } // @@ -4061,28 +2884,22 @@ TEST_P(ServiceChainParamTest, TransitNetworkToggleAllowTransit) { // (core-i5)(green-i6)(green) // TEST_P(ServiceChainParamTest, TransitNetworkMultipleNetworks) { - string content = - FileRead("controller/src/bgp/testdata/service_chain_test_2.xml"); - parser_.Parse(content); - task_util::WaitForIdle(); + ParseConfigFile("controller/src/bgp/testdata/service_chain_test_2.xml"); AddConnection("blue", "blue-i1"); AddConnection("core", "core-i3"); AddConnection("core", "core-i5"); - task_util::WaitForIdle(); // Add more specific routes to red and green AddInetRoute(NULL, "red", "192.168.3.101/32", 100); AddInetRoute(NULL, "red", "192.168.3.102/32", 100); AddInetRoute(NULL, "green", "192.168.4.101/32", 100); AddInetRoute(NULL, "green", "192.168.4.102/32", 100); - task_util::WaitForIdle(); // Add Ext connect routes to red and green AddInetRoute(NULL, "red", "10.1.3.1/32", 100); AddInetRoute(NULL, "red", "10.1.3.2/32", 100); AddInetRoute(NULL, "green", "10.1.4.1/32", 100); AddInetRoute(NULL, "green", "10.1.4.2/32", 100); - task_util::WaitForIdle(); // Add Connected routes for the 3 chains AddConnectedRoute(1, NULL, "192.168.1.253/32", 100, "20.1.1.1"); @@ -4119,7 +2936,6 @@ TEST_P(ServiceChainParamTest, TransitNetworkMultipleNetworks) { DeleteConnectedRoute(1, NULL, "192.168.1.253/32"); DeleteConnectedRoute(2, NULL, "192.168.2.253/32"); DeleteConnectedRoute(3, NULL, "192.168.2.252/32"); - task_util::WaitForIdle(); } INSTANTIATE_TEST_CASE_P(Instance, ServiceChainParamTest, From d717aa729d4e880a07c91894e0cd6efc9f6c8ec9 Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Fri, 17 Oct 2014 10:24:00 +0530 Subject: [PATCH 031/218] Schema changes for VCPE feature. -Define an object to represent subnet -Define a link from this subnet object to virtual-machine-interface object Change-Id: I2fdc56d4be68bec32f3b2f45ba735e9efea1f733 --- src/schema/vnc_cfg.xsd | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd index deede79ab91..aa7e826b282 100644 --- a/src/schema/vnc_cfg.xsd +++ b/src/schema/vnc_cfg.xsd @@ -902,6 +902,15 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> Link('instance-ip-virtual-machine-interface', 'instance-ip', 'virtual-machine-interface', ['ref']) --> + + + + + + hanged") + message = "command:" + cmd + " ---> hanged" + ssdlog = StorageStatsDaemonLog(message = message) + self.call_send(ssdlog) return None return p.stdout.read() @@ -655,7 +657,11 @@ def parse_args(args_str): defaults = { 'disc_server_ip': '127.0.0.1', 'disc_server_port': 5998, - 'node_type': 'storage-compute' + 'node_type': 'storage-compute', + 'log_local': True, + 'log_level': 'SYS_NOTICE', + 'log_category': '', + 'log_file': Sandesh._DEFAULT_LOG_FILE } if args.conf_file: @@ -680,8 +686,16 @@ def parse_args(args_str): help="IP address of the discovery server") parser.add_argument("--disc_server_port", help="Port of the discovery server") + parser.add_argument("--log_local", action="store_true", + help="Enable local logging of sandesh messages") parser.add_argument("--node_type", help="node type of the storage") + parser.add_argument("--log_level", + help="Severity level for local logging of sandesh messages") + parser.add_argument("--log_category", + help="Category filter for local logging of sandesh messages") + parser.add_argument("--log_file", + help="Filename for the logs to be written to") args = parser.parse_args(remaining_argv) return args @@ -693,14 +707,6 @@ def main(args_str=None): args_str = ' '.join(sys.argv[1:]) args = parse_args(args_str) - # dump the read values - sys.stderr.write("node_type: " + args.node_type + "\n") - sys.stderr.write("Discovery ip: " + args.disc_server_ip + "\n") - sys.stderr.write("Discovery port: " + str(args.disc_server_port) + "\n") - - #syslog logging - syslog.openlog(logoption=syslog.LOG_PID) - # create event manager prog = EventManager(args.node_type) collector_addr = [] @@ -729,7 +735,14 @@ def main(args_str=None): HttpPortStorageStatsmgr, ['stats_daemon.sandesh.storage'], _disc) + + sandesh_global.set_logging_params( + enable_local_log=args.log_local, + category=args.log_category, + level=args.log_level, + file=args.log_file) gevent.joinall([gevent.spawn(prog.runforever, sandesh_global)]) + if __name__ == '__main__': main() diff --git a/src/storage/stats-daemon/storage.sandesh b/src/storage/stats-daemon/storage.sandesh index f3f8cb1ee9b..fcc79f71a9f 100644 --- a/src/storage/stats-daemon/storage.sandesh +++ b/src/storage/stats-daemon/storage.sandesh @@ -28,6 +28,10 @@ struct OsdStats { 6: u64 op_w_latency; } +systemlog sandesh StorageStatsDaemonLog { + 1: string message; +} + struct ComputeStorageOsdState { 1: string status; } From 33d7d6f1a92773e59c326969fbf5e21329485ee0 Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Tue, 26 Aug 2014 12:01:21 -0700 Subject: [PATCH 154/218] Verify ASN in SecurityGroup extended community Motivation: In multi-cluster scenario each VNC allocates security group ids locally. This is problematic because an id from one cluster is meaningless in the other clusters. A mechanism to assign globally significant ids is needed. Further, the control nodes need some logic to distinugiush between local and global ids. Solution: Assume an API to assign a global id to a security group. Global ids are assigned from a pre-decided range which does not overlap with local ids. Control node advertises both local and global ids using the SecurityGroup extended community. When a SecurityGroup community is received, Control node ignores it if the ASN is different than it's local ASN. An exception is made for the case where the id belongs to the global range. Outstanding: API server and schema transformer changes to assign global id to security group. Misc: Clean up a few mock agent APIs. Change-Id: Ibc8d555ebfc80227b1848fbe1eb5dee7d63be19a Partial-Bug: 1381145 --- src/bgp/bgp_table.cc | 4 + src/bgp/bgp_table.h | 1 + src/bgp/routing-instance/routing_instance.cc | 4 + src/bgp/routing-instance/routing_instance.h | 2 + src/bgp/security_group/security_group.cc | 32 +++- src/bgp/security_group/security_group.h | 8 +- src/bgp/test/bgp_stress_test.cc | 3 +- src/bgp/test/bgp_xmpp_inetvpn_test.cc | 166 ++++++++++++++++++- src/bgp/test/xmpp_ecmp_test.cc | 8 +- src/bgp/xmpp_message_builder.cc | 7 +- src/control-node/test/network_agent_mock.cc | 96 ++++++----- src/control-node/test/network_agent_mock.h | 34 ++-- 12 files changed, 285 insertions(+), 80 deletions(-) diff --git a/src/bgp/bgp_table.cc b/src/bgp/bgp_table.cc index 1e7e814b6f5..e808e5fda16 100644 --- a/src/bgp/bgp_table.cc +++ b/src/bgp/bgp_table.cc @@ -85,6 +85,10 @@ BgpServer *BgpTable::server() { return rtinstance_->server(); } +const BgpServer *BgpTable::server() const { + return rtinstance_->server(); +} + // // Find the RibOut for the given RibExportPolicy. // diff --git a/src/bgp/bgp_table.h b/src/bgp/bgp_table.h index 44730271c27..d02533c62f3 100644 --- a/src/bgp/bgp_table.h +++ b/src/bgp/bgp_table.h @@ -101,6 +101,7 @@ class BgpTable : public RouteTable { const RoutingInstance *routing_instance() const { return rtinstance_; } virtual void set_routing_instance(RoutingInstance *rtinstance); BgpServer *server(); + const BgpServer *server() const; virtual void Input(DBTablePartition *root, DBClient *client, DBRequest *req); diff --git a/src/bgp/routing-instance/routing_instance.cc b/src/bgp/routing-instance/routing_instance.cc index cebda4cbe84..a563a71a1f5 100644 --- a/src/bgp/routing-instance/routing_instance.cc +++ b/src/bgp/routing-instance/routing_instance.cc @@ -774,6 +774,10 @@ BgpServer *RoutingInstance::server() { return mgr_->server(); } +const BgpServer *RoutingInstance::server() const { + return mgr_->server(); +} + void RoutingInstance::ClearFamilyRouteTarget(Address::Family vrf_family, Address::Family vpn_family) { BgpTable *table = GetTable(vrf_family); diff --git a/src/bgp/routing-instance/routing_instance.h b/src/bgp/routing-instance/routing_instance.h index c393d797c33..0b2a9335331 100644 --- a/src/bgp/routing-instance/routing_instance.h +++ b/src/bgp/routing-instance/routing_instance.h @@ -106,6 +106,7 @@ class RoutingInstance { RoutingInstanceInfo GetDataCollection(const char *operation); BgpServer *server(); + const BgpServer *server() const; // Remove import and export route target // and Leave corresponding RtGroup @@ -246,6 +247,7 @@ class RoutingInstanceMgr { size_t count() const { return instances_.count(); } BgpServer *server() { return server_; } + const BgpServer *server() const { return server_; } LifetimeActor *deleter(); private: diff --git a/src/bgp/security_group/security_group.cc b/src/bgp/security_group/security_group.cc index ea6e2e6434f..cddd2a6e30f 100644 --- a/src/bgp/security_group/security_group.cc +++ b/src/bgp/security_group/security_group.cc @@ -6,9 +6,11 @@ #include "base/parse_object.h" #include -using namespace std; -SecurityGroup::SecurityGroup(int asn, uint32_t sgid) { +using std::copy; +using std::string; + +SecurityGroup::SecurityGroup(as_t asn, uint32_t sgid) { data_[0] = 0x80; data_[1] = 0x04; put_value(&data_[2], 2, asn); @@ -19,18 +21,30 @@ SecurityGroup::SecurityGroup(const bytes_type &data) { copy(data.begin(), data.end(), data_.begin()); } +as_t SecurityGroup::as_number() const { + if (data_[0] == 0x80 && data_[1] == 0x04) { + as_t as_number = get_value(&data_[2], 2); + return as_number; + } + return 0; +} + uint32_t SecurityGroup::security_group_id() const { - uint8_t data[SecurityGroup::kSize]; - copy(data_.begin(), data_.end(), &data[0]); - if (data[0] == 0x80 && data[1] == 0x04) { - uint32_t num = get_value(data + 4, 4); + if (data_[0] == 0x80 && data_[1] == 0x04) { + uint32_t num = get_value(&data_[4], 4); return num; } return 0; } -std::string SecurityGroup::ToString() { +bool SecurityGroup::IsGlobal() const { + uint32_t sgid = security_group_id(); + return (sgid >= kMinGlobalId && sgid <= kMaxGlobalId); +} + +string SecurityGroup::ToString() { char temp[50]; - snprintf(temp, sizeof(temp), "security group: %d", security_group_id()); - return std::string(temp); + snprintf(temp, sizeof(temp), "secgroup:%u:%u", + as_number(), security_group_id()); + return string(temp); } diff --git a/src/bgp/security_group/security_group.h b/src/bgp/security_group/security_group.h index f041af0ff76..c69579a8fc6 100644 --- a/src/bgp/security_group/security_group.h +++ b/src/bgp/security_group/security_group.h @@ -9,16 +9,21 @@ #include #include "base/parse_object.h" +#include "bgp/bgp_common.h" class SecurityGroup { public: static const int kSize = 8; + static const uint32_t kMinGlobalId = 1000000; + static const uint32_t kMaxGlobalId = 1999999; typedef boost::array bytes_type; - SecurityGroup(int asn, uint32_t id); + SecurityGroup(as_t asn, uint32_t id); explicit SecurityGroup(const bytes_type &data); + as_t as_number() const; uint32_t security_group_id() const; + bool IsGlobal() const; const bytes_type &GetExtCommunity() const { return data_; @@ -28,6 +33,7 @@ class SecurityGroup { return get_value(data_.begin(), 8); } std::string ToString(); + private: bytes_type data_; }; diff --git a/src/bgp/test/bgp_stress_test.cc b/src/bgp/test/bgp_stress_test.cc index 5d27cc33045..6eacd96db8d 100644 --- a/src/bgp/test/bgp_stress_test.cc +++ b/src/bgp/test/bgp_stress_test.cc @@ -1675,8 +1675,7 @@ void BgpStressTest::DeleteXmppRoute(int instance_id, int agent_id, mcast_prefix = task_util::Ip4PrefixIncrement(mcast_prefix, route_id); xmpp_agents_[agent_id]->DeleteRoute(GetInstanceName(instance_id), - prefix.ToString(), - GetAgentNexthop(agent_id, route_id)); + prefix.ToString()); xmpp_agents_[agent_id]->DeleteMcastRoute(GetInstanceName(instance_id), "1/8/" + mcast_prefix.ip4_addr().to_string() + "," + prefix.ToString()); diff --git a/src/bgp/test/bgp_xmpp_inetvpn_test.cc b/src/bgp/test/bgp_xmpp_inetvpn_test.cc index 0bb9161a0f4..a886c218fd2 100644 --- a/src/bgp/test/bgp_xmpp_inetvpn_test.cc +++ b/src/bgp/test/bgp_xmpp_inetvpn_test.cc @@ -3,11 +3,13 @@ */ #include +#include #include "base/test/task_test_util.h" #include "bgp/bgp_factory.h" #include "bgp/bgp_session_manager.h" #include "bgp/bgp_xmpp_channel.h" +#include "bgp/security_group/security_group.h" #include "bgp/test/bgp_server_test_util.h" #include "control-node/control_node.h" #include "control-node/test/network_agent_mock.h" @@ -18,6 +20,7 @@ #include "xmpp/xmpp_server.h" using namespace std; +using boost::assign::list_of; static const char *config_2_control_nodes = "\ \ @@ -83,6 +86,42 @@ static const char *config_2_control_nodes_no_vn_info = "\ \ "; +static const char *config_2_control_nodes_different_asn = "\ +\ + \ + 64511\ + 192.168.0.1\ +
127.0.0.1
\ + %d\ + \ + \ + route-target\ + inet-vpn\ + \ + \ +
\ + \ + 64512\ + 192.168.0.2\ +
127.0.0.2
\ + %d\ + \ + \ + route-target\ + inet-vpn\ + \ + \ +
\ + \ + 1\ + \ + \ + blue\ + target:1:1\ + \ +
\ +"; + // // Control Nodes X and Y. // Agents A and B. @@ -168,16 +207,19 @@ class BgpXmppInetvpn2ControlNodeTest : public ::testing::Test { bool CheckRoute(test::NetworkAgentMockPtr agent, string net, string prefix, string nexthop, int local_pref, const string &encap, - const string &origin_vn) { + const string &origin_vn, const vector sgids) { const autogen::ItemType *rt = agent->RouteLookup(net, prefix); if (!rt) return false; if (rt->entry.next_hops.next_hop[0].address != nexthop) return false; - if (rt->entry.local_preference != local_pref) + if (local_pref && rt->entry.local_preference != local_pref) return false; if (!origin_vn.empty() && rt->entry.virtual_network != origin_vn) return false; + if (!sgids.empty() && + rt->entry.security_group_list.security_group != sgids) + return false; autogen::TunnelEncapsulationListType rt_encap = rt->entry.next_hops.next_hop[0].tunnel_encapsulation_list; @@ -188,9 +230,16 @@ class BgpXmppInetvpn2ControlNodeTest : public ::testing::Test { void VerifyRouteExists(test::NetworkAgentMockPtr agent, string net, string prefix, string nexthop, int local_pref, - const string &encap = string(), const string &origin_vn = string()) { + const string &encap = string(), const string &origin_vn = string(), + const vector sgids = vector()) { + TASK_UTIL_EXPECT_TRUE(CheckRoute( + agent, net, prefix, nexthop, local_pref, encap, origin_vn, sgids)); + } + + void VerifyRouteExists(test::NetworkAgentMockPtr agent, string net, + string prefix, string nexthop, const vector sgids) { TASK_UTIL_EXPECT_TRUE(CheckRoute( - agent, net, prefix, nexthop, local_pref, encap, origin_vn)); + agent, net, prefix, nexthop, 0, string(), string(), sgids)); } void VerifyRouteNoExists(test::NetworkAgentMockPtr agent, string net, @@ -464,6 +513,115 @@ TEST_F(BgpXmppInetvpn2ControlNodeTest, VirtualNetworkIndexChange) { agent_b_->SessionDown(); } +TEST_F(BgpXmppInetvpn2ControlNodeTest, SecurityGroupsSameAsn) { + Configure(); + task_util::WaitForIdle(); + + // Create XMPP Agent A connected to XMPP server X. + agent_a_.reset( + new test::NetworkAgentMock(&evm_, "agent-a", xs_x_->GetPort(), + "127.0.0.1", "127.0.0.1")); + TASK_UTIL_EXPECT_TRUE(agent_a_->IsEstablished()); + + // Create XMPP Agent B connected to XMPP server Y. + agent_b_.reset( + new test::NetworkAgentMock(&evm_, "agent-b", xs_y_->GetPort(), + "127.0.0.2", "127.0.0.2")); + TASK_UTIL_EXPECT_TRUE(agent_b_->IsEstablished()); + + // Register to blue instance + agent_a_->Subscribe("blue", 1); + agent_b_->Subscribe("blue", 1); + + // Add route from agent A. + stringstream route_a; + route_a << "10.1.1.1/32"; + test::NextHops next_hops; + test::NextHop next_hop("192.168.1.1"); + next_hops.push_back(next_hop); + vector sgids = list_of + (SecurityGroup::kMaxGlobalId - 1)(SecurityGroup::kMaxGlobalId + 1) + (SecurityGroup::kMaxGlobalId - 2)(SecurityGroup::kMaxGlobalId + 2); + test::RouteAttributes attributes(sgids); + agent_a_->AddRoute("blue", route_a.str(), next_hops, attributes); + task_util::WaitForIdle(); + + // Verify that route showed up on agents A and B with expected sgids. + sort(sgids.begin(), sgids.end()); + VerifyRouteExists( + agent_a_, "blue", route_a.str(), "192.168.1.1", sgids); + VerifyRouteExists( + agent_b_, "blue", route_a.str(), "192.168.1.1", sgids); + + // Delete route from agent A. + agent_a_->DeleteRoute("blue", route_a.str()); + task_util::WaitForIdle(); + + // Verify that route is deleted at agents A and B. + VerifyRouteNoExists(agent_a_, "blue", route_a.str()); + VerifyRouteNoExists(agent_b_, "blue", route_a.str()); + + // Close the sessions. + agent_a_->SessionDown(); + agent_b_->SessionDown(); +} + +TEST_F(BgpXmppInetvpn2ControlNodeTest, SecurityGroupsDifferentAsn) { + Configure(config_2_control_nodes_different_asn); + task_util::WaitForIdle(); + + // Create XMPP Agent A connected to XMPP server X. + agent_a_.reset( + new test::NetworkAgentMock(&evm_, "agent-a", xs_x_->GetPort(), + "127.0.0.1", "127.0.0.1")); + TASK_UTIL_EXPECT_TRUE(agent_a_->IsEstablished()); + + // Create XMPP Agent B connected to XMPP server Y. + agent_b_.reset( + new test::NetworkAgentMock(&evm_, "agent-b", xs_y_->GetPort(), + "127.0.0.2", "127.0.0.2")); + TASK_UTIL_EXPECT_TRUE(agent_b_->IsEstablished()); + + // Register to blue instance + agent_a_->Subscribe("blue", 1); + agent_b_->Subscribe("blue", 1); + + // Add route from agent A. + stringstream route_a; + route_a << "10.1.1.1/32"; + test::NextHops next_hops; + test::NextHop next_hop("192.168.1.1"); + next_hops.push_back(next_hop); + vector sgids = list_of + (SecurityGroup::kMaxGlobalId - 1)(SecurityGroup::kMaxGlobalId + 1) + (SecurityGroup::kMaxGlobalId - 2)(SecurityGroup::kMaxGlobalId + 2); + test::RouteAttributes attributes(sgids); + agent_a_->AddRoute("blue", route_a.str(), next_hops, attributes); + task_util::WaitForIdle(); + + // Verify that route showed up on agents A and B with expected sgids. + vector global_sgids = list_of + (SecurityGroup::kMaxGlobalId - 1)(SecurityGroup::kMaxGlobalId - 2); + sort(sgids.begin(), sgids.end()); + sort(global_sgids.begin(), global_sgids.end()); + VerifyRouteExists( + agent_a_, "blue", route_a.str(), "192.168.1.1", sgids); + VerifyRouteExists( + agent_b_, "blue", route_a.str(), "192.168.1.1", global_sgids); + + // Delete route from agent A. + agent_a_->DeleteRoute("blue", route_a.str()); + task_util::WaitForIdle(); + + // Verify that route is deleted at agents A and B. + VerifyRouteNoExists(agent_a_, "blue", route_a.str()); + VerifyRouteNoExists(agent_b_, "blue", route_a.str()); + + // Close the sessions. + agent_a_->SessionDown(); + agent_b_->SessionDown(); +} + class TestEnvironment : public ::testing::Environment { virtual ~TestEnvironment() { } virtual void SetUp() { diff --git a/src/bgp/test/xmpp_ecmp_test.cc b/src/bgp/test/xmpp_ecmp_test.cc index 8d7ac3d54b2..d7447f3e01e 100644 --- a/src/bgp/test/xmpp_ecmp_test.cc +++ b/src/bgp/test/xmpp_ecmp_test.cc @@ -628,7 +628,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { // Bring down agent_a or agent_a's routes. if (!flap) { if (inet_) { - agent_a_->DeleteRoute(net_1_, "10.0.1.1/32", nexthops_a); + agent_a_->DeleteRoute(net_1_, "10.0.1.1/32"); } if (enet_) { agent_a_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32", @@ -654,7 +654,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { // Bring down agent_b or agent_b's routes. if (!flap) { if (inet_) { - agent_b_->DeleteRoute(net_2_, "10.0.1.1/32", nexthops_b); + agent_b_->DeleteRoute(net_2_, "10.0.1.1/32"); } if (enet_) { agent_b_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32", @@ -679,7 +679,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { // Bring down agent_c or agent_c's routes. if (!flap) { if (inet_) { - agent_c_->DeleteRoute(net_1_, "10.0.1.1/32", nexthops_c); + agent_c_->DeleteRoute(net_1_, "10.0.1.1/32"); } if (enet_) { agent_c_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32", @@ -703,7 +703,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { // Bring down agent_d or agent_d's routes. if (!flap) { if (inet_) { - agent_d_->DeleteRoute(net_2_, "10.0.1.1/32", nexthops_d); + agent_d_->DeleteRoute(net_2_, "10.0.1.1/32"); } if (enet_) { agent_d_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32", diff --git a/src/bgp/xmpp_message_builder.cc b/src/bgp/xmpp_message_builder.cc index 898b15f3d9b..71cfd443351 100644 --- a/src/bgp/xmpp_message_builder.cc +++ b/src/bgp/xmpp_message_builder.cc @@ -63,12 +63,15 @@ class BgpXmppMessage : public Message { if (ext_community == NULL) return; + as_t local_as_number = table_->server()->autonomous_system(); for (ExtCommunity::ExtCommunityList::const_iterator iter = ext_community->communities().begin(); iter != ext_community->communities().end(); ++iter) { if (ExtCommunity::is_security_group(*iter)) { - SecurityGroup security_group(*iter); - security_group_list_.push_back(security_group.security_group_id()); + SecurityGroup sg(*iter); + if (sg.as_number() != local_as_number && !sg.IsGlobal()) + continue; + security_group_list_.push_back(sg.security_group_id()); } if (ExtCommunity::is_mac_mobility(*iter)) { MacMobility mm(*iter); diff --git a/src/control-node/test/network_agent_mock.cc b/src/control-node/test/network_agent_mock.cc index fbf8e17a328..64250a3c2a1 100644 --- a/src/control-node/test/network_agent_mock.cc +++ b/src/control-node/test/network_agent_mock.cc @@ -5,6 +5,7 @@ #include "network_agent_mock.h" #include +#include #include #include "base/logging.h" @@ -26,6 +27,7 @@ using namespace std; using namespace pugi; using boost::asio::ip::address; +using boost::assign::list_of; namespace test { @@ -252,15 +254,14 @@ XmppDocumentMock::XmppDocumentMock(const std::string &hostname) } pugi::xml_document *XmppDocumentMock::RouteAddXmlDoc( - const std::string &network, const std::string &prefix, - NextHops nexthops, int local_pref) { - return RouteAddDeleteXmlDoc(network, prefix, true, nexthops, local_pref); + const std::string &network, const std::string &prefix, + const NextHops &nexthops, const RouteAttributes &attributes) { + return RouteAddDeleteXmlDoc(network, prefix, true, nexthops, attributes); } pugi::xml_document *XmppDocumentMock::RouteDeleteXmlDoc( - const std::string &network, const std::string &prefix, - NextHops nexthops) { - return RouteAddDeleteXmlDoc(network, prefix, false, nexthops); + const std::string &network, const std::string &prefix) { + return RouteAddDeleteXmlDoc(network, prefix, false); } pugi::xml_document *XmppDocumentMock::Inet6RouteAddXmlDoc( @@ -348,7 +349,7 @@ pugi::xml_document *XmppDocumentMock::SubUnsubXmlDoc( pugi::xml_document *XmppDocumentMock::RouteAddDeleteXmlDoc( const std::string &network, const std::string &prefix, bool add, - NextHops nexthops, int local_pref) { + const NextHops &nexthops, const RouteAttributes &attributes) { xdoc_->reset(); xml_node pubsub = PubSubHeader(kNetworkServiceJID); xml_node pub = pubsub.append_child("publish"); @@ -361,25 +362,37 @@ pugi::xml_document *XmppDocumentMock::RouteAddDeleteXmlDoc( rt_entry.entry.nlri.af = BgpAf::IPv4; rt_entry.entry.nlri.safi = BgpAf::Unicast; rt_entry.entry.nlri.address = prefix; - rt_entry.entry.security_group_list.security_group.push_back(101); - rt_entry.entry.local_preference = local_pref; - - if (nexthops.empty()) { - NextHop nexthop = NextHop(localaddr(), 0); - nexthop.tunnel_encapsulations_.push_back("gre"); - nexthops.push_back(nexthop); - } - BOOST_FOREACH(NextHop nexthop, nexthops) { - autogen::NextHopType item_nexthop; + if (add) { + rt_entry.entry.local_preference = attributes.local_pref; + rt_entry.entry.sequence_number = attributes.sequence; + if (attributes.sgids.size()) { + rt_entry.entry.security_group_list.security_group = attributes.sgids; + } else { + rt_entry.entry.security_group_list.security_group.push_back(101); + } - item_nexthop.af = BgpAf::IPv4; - assert(!nexthop.address_.empty()); - item_nexthop.address = nexthop.address_; - item_nexthop.label = add ? (nexthop.label_ ?: label_alloc_++) : - 0xFFFFF; - item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = nexthop.tunnel_encapsulations_; - rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + if (nexthops.empty()) { + autogen::NextHopType item_nexthop; + item_nexthop.af = BgpAf::IPv4; + item_nexthop.address = localaddr(); + item_nexthop.label = label_alloc_++; + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = + list_of("gre"); + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + } else { + BOOST_FOREACH(const NextHop &nexthop, nexthops) { + autogen::NextHopType item_nexthop; + item_nexthop.af = BgpAf::IPv4; + assert(!nexthop.address_.empty()); + item_nexthop.address = nexthop.address_; + item_nexthop.label = + nexthop.label_ ? nexthop.label_ : label_alloc_++; + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = + nexthop.tunnel_encapsulations_; + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + } + } } xml_node item = pub.append_child("item"); @@ -893,47 +906,42 @@ void NetworkAgentMock::AddRoute(const string &network_name, const string &prefix, const string nexthop, int local_pref) { NextHops nexthops; - if (!nexthop.empty()) { nexthops.push_back(NextHop(nexthop, 0)); } + RouteAttributes attributes(local_pref); AgentPeer *peer = GetAgent(); xml_document *xdoc = - impl_->RouteAddXmlDoc(network_name, prefix, nexthops, local_pref); - + impl_->RouteAddXmlDoc(network_name, prefix, nexthops, attributes); peer->SendDocument(xdoc); } -void NetworkAgentMock::DeleteRoute(const string &network_name, - const string &prefix, const string nexthop) { - NextHops nexthops; - - if (!nexthop.empty()) { - nexthops.push_back(NextHop(nexthop, 0)); - } - +void NetworkAgentMock::AddRoute(const string &network_name, + const string &prefix, + const NextHops &nexthops, + int local_pref) { + RouteAttributes attributes(local_pref); AgentPeer *peer = GetAgent(); - xml_document *xdoc = impl_->RouteDeleteXmlDoc(network_name, prefix, - nexthops); + xml_document *xdoc = + impl_->RouteAddXmlDoc(network_name, prefix, nexthops, attributes); peer->SendDocument(xdoc); } void NetworkAgentMock::AddRoute(const string &network_name, - const string &prefix, NextHops nexthops, - int local_pref) { + const string &prefix, + const NextHops &nexthops, + const RouteAttributes &attributes) { AgentPeer *peer = GetAgent(); xml_document *xdoc = - impl_->RouteAddXmlDoc(network_name, prefix, nexthops, local_pref); - + impl_->RouteAddXmlDoc(network_name, prefix, nexthops, attributes); peer->SendDocument(xdoc); } void NetworkAgentMock::DeleteRoute(const string &network_name, - const string &prefix, NextHops nexthops) { + const string &prefix) { AgentPeer *peer = GetAgent(); - xml_document *xdoc = impl_->RouteDeleteXmlDoc(network_name, prefix, - nexthops); + xml_document *xdoc = impl_->RouteDeleteXmlDoc(network_name, prefix); peer->SendDocument(xdoc); } diff --git a/src/control-node/test/network_agent_mock.h b/src/control-node/test/network_agent_mock.h index 60247c92972..c04615cafa8 100644 --- a/src/control-node/test/network_agent_mock.h +++ b/src/control-node/test/network_agent_mock.h @@ -54,6 +54,10 @@ struct RouteAttributes { RouteAttributes(uint32_t lpref, uint32_t seq) : local_pref(lpref), sequence(seq), sgids(std::vector()) { } + RouteAttributes(uint32_t lpref) + : local_pref(lpref), sequence(kDefaultSequence), + sgids(std::vector()) { + } RouteAttributes(const std::vector &sg) : local_pref(kDefaultLocalPref), sequence(kDefaultSequence), sgids(sg) { @@ -71,6 +75,10 @@ struct RouteAttributes { struct NextHop { NextHop() : label_(0) { } + NextHop(std::string address) : + address_(address), label_(0) { + tunnel_encapsulations_.push_back("gre"); + } NextHop(std::string address, uint32_t label, std::string tun1 = "gre") : address_(address), label_(label) { if (tun1 == "all") { @@ -130,13 +138,12 @@ class XmppDocumentMock { static const char *kPubSubNS; XmppDocumentMock(const std::string &hostname); - pugi::xml_document *RouteAddXmlDoc(const std::string &network, - const std::string &prefix, - NextHops nexthops = NextHops(), - int local_pref = 0); + pugi::xml_document *RouteAddXmlDoc(const std::string &network, + const std::string &prefix, + const NextHops &nexthops = NextHops(), + const RouteAttributes &attributes = RouteAttributes()); pugi::xml_document *RouteDeleteXmlDoc(const std::string &network, - const std::string &prefix, - NextHops nexthops = NextHops()); + const std::string &prefix); pugi::xml_document *Inet6RouteAddXmlDoc(const std::string &network, const std::string &prefix, NextHops nexthops, @@ -182,8 +189,9 @@ class XmppDocumentMock { const std::string &prefix, Oper oper, NextHops nexthops, const RouteAttributes &attributes); pugi::xml_document *RouteAddDeleteXmlDoc(const std::string &network, - const std::string &prefix, bool add, NextHops nexthop, - int local_pref = 0); + const std::string &prefix, bool add, + const NextHops &nexthop = NextHops(), + const RouteAttributes &attributes = RouteAttributes()); pugi::xml_document *RouteEnetAddDeleteXmlDoc(const std::string &network, const std::string &prefix, NextHops nexthop, const RouteParams *params, bool add); @@ -314,13 +322,11 @@ class NetworkAgentMock { void AddRoute(const std::string &network, const std::string &prefix, const std::string nexthop = "", int local_pref = 0); - void DeleteRoute(const std::string &network, const std::string &prefix, - const std::string nexthop = ""); - void AddRoute(const std::string &network, const std::string &prefix, - NextHops nexthops, int local_pref = 0); - void DeleteRoute(const std::string &network, const std::string &prefix, - NextHops nexthops); + const NextHops &nexthops, int local_pref = 0); + void AddRoute(const std::string &network, const std::string &prefix, + const NextHops &nexthops, const RouteAttributes &attributes); + void DeleteRoute(const std::string &network, const std::string &prefix); void AddInet6Route(const std::string &network, const std::string &prefix, const NextHops &nexthops, From e1adda3221a3a73e5f161bfc966fafe089000d23 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Wed, 29 Oct 2014 22:20:21 -0700 Subject: [PATCH 155/218] Add logic to check we don't program routes which points to the tor itself. --- .../ovsdb_client/logical_switch_ovsdb.cc | 12 +++++++++++- .../ovsdb_client/logical_switch_ovsdb.h | 2 ++ .../ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c | 10 +++++++--- .../ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h | 2 +- .../ovsdb_client/physical_switch_ovsdb.cc | 13 ++++++++++++- .../ovsdb_client/physical_switch_ovsdb.h | 3 +++ .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 12 +++++++++--- 7 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index bcec2bbe659..ee5f8bac605 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -43,9 +43,18 @@ LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, vxlan_id_(ovsdb_wrapper_logical_switch_tunnel_key(entry)), mcast_local_row_(NULL), mcast_remote_row_(NULL), old_mcast_remote_row_(NULL) { -}; +} + +Ip4Address &LogicalSwitchEntry::physical_switch_tunnel_ip() { + PhysicalSwitchEntry *p_switch = + static_cast(physical_switch_.get()); + return p_switch->tunnel_ip(); +} void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) { + PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table(); + PhysicalSwitchEntry key(p_table, device_name_.c_str()); + physical_switch_ = p_table->GetReference(&key); struct ovsdb_idl_row *row = ovsdb_wrapper_add_logical_switch(txn, ovs_entry_, name_.c_str(), vxlan_id_); @@ -78,6 +87,7 @@ void LogicalSwitchEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { } void LogicalSwitchEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { + physical_switch_ = NULL; if (mcast_local_row_ != NULL) { ovsdb_wrapper_delete_mcast_mac_local(mcast_local_row_); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h index 6a3f93ea749..b81a5409068 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h @@ -46,6 +46,7 @@ class LogicalSwitchEntry : public OvsdbDBEntry { LogicalSwitchEntry(OvsdbDBObject *table, struct ovsdb_idl_row *entry); + Ip4Address &physical_switch_tunnel_ip(); void AddMsg(struct ovsdb_idl_txn *); void ChangeMsg(struct ovsdb_idl_txn *); void DeleteMsg(struct ovsdb_idl_txn *); @@ -62,6 +63,7 @@ class LogicalSwitchEntry : public OvsdbDBEntry { friend class LogicalSwitchTable; std::string name_; std::string device_name_; + KSyncEntryPtr physical_switch_; int64_t vxlan_id_; struct ovsdb_idl_row *mcast_local_row_; struct ovsdb_idl_row *mcast_remote_row_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index a1bfe89b111..175d016bfb3 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -183,12 +183,16 @@ ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row) return ps->name; } -char * -ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row) +const char * +ovsdb_wrapper_physical_switch_tunnel_ip(struct ovsdb_idl_row *row) { struct vteprec_physical_switch *ps = row ? CONTAINER_OF(row, struct vteprec_physical_switch, header_) : NULL; - return ps->management_ips[0]; + if (ps->n_tunnel_ips == 0) { + return "0.0.0.0"; + } + /* return the first tunnel ip. */ + return ps->tunnel_ips[0]; } /* logical switch */ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index c088b99d4f6..aca6ed785b1 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -43,7 +43,7 @@ struct jsonrpc_msg *ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn); /* Physical Switch */ char *ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row); -char *ovsdb_wrapper_physical_switch_ip(struct ovsdb_idl_row *row); +const char *ovsdb_wrapper_physical_switch_tunnel_ip(struct ovsdb_idl_row *row); /* Logical Switch */ char *ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc index 209039f8e39..01494606da8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -13,12 +13,22 @@ using OVSDB::PhysicalSwitchEntry; using OVSDB::PhysicalSwitchTable; PhysicalSwitchEntry::PhysicalSwitchEntry(PhysicalSwitchTable *table, - const std::string &name) : OvsdbEntry(table), name_(name) { + const std::string &name) : OvsdbEntry(table), name_(name), + tunnel_ip_() { } PhysicalSwitchEntry::~PhysicalSwitchEntry() { } +Ip4Address &PhysicalSwitchEntry::tunnel_ip() { + return tunnel_ip_; +} + +void PhysicalSwitchEntry::set_tunnel_ip(std::string ip) { + boost::system::error_code ec; + tunnel_ip_ = Ip4Address::from_string(ip, ec); +} + bool PhysicalSwitchEntry::IsLess(const KSyncEntry &entry) const { const PhysicalSwitchEntry &ps_entry = static_cast(entry); @@ -69,6 +79,7 @@ void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op, entry = static_cast(Create(&key)); entry->SendTrace(PhysicalSwitchEntry::ADD); } + entry->set_tunnel_ip(ovsdb_wrapper_physical_switch_tunnel_ip(row)); } else { assert(0); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h index 4445b779f03..cfe42b8529c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h @@ -29,6 +29,8 @@ class PhysicalSwitchEntry : public OvsdbEntry { PhysicalSwitchEntry(PhysicalSwitchTable *table, const std::string &name); ~PhysicalSwitchEntry(); + Ip4Address &tunnel_ip(); + void set_tunnel_ip(std::string ip); bool IsLess(const KSyncEntry&) const; std::string ToString() const {return "Physical Switch";} KSyncEntry* UnresolvedReference(); @@ -37,6 +39,7 @@ class PhysicalSwitchEntry : public OvsdbEntry { friend class PhysicalSwitchTable; std::string name_; + Ip4Address tunnel_ip_; DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchEntry); }; }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index c11c7bb5d7b..6db4d9bba8c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -69,7 +69,15 @@ void UnicastMacRemoteEntry::PostDelete() { } void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { - if (self_exported_route_) { + boost::system::error_code ec; + Ip4Address dest_ip = Ip4Address::from_string(dest_ip_, ec); + LogicalSwitchEntry *logical_switch = + static_cast(logical_switch_.get()); + if (self_exported_route_ || + dest_ip == logical_switch->physical_switch_tunnel_ip()) { + // if the route is self exported or if dest tunnel end-point points to + // the physical switch itself then donot export this route to OVSDB + DeleteMsg(txn); return; } if (ovs_entry_ == NULL && !dest_ip_.empty()) { @@ -85,8 +93,6 @@ void UnicastMacRemoteEntry::AddMsg(struct ovsdb_idl_txn *txn) { struct ovsdb_idl_row *pl_row = NULL; if (pl_entry) pl_row = pl_entry->ovs_entry(); - LogicalSwitchEntry *logical_switch = - static_cast(logical_switch_.get()); obvsdb_wrapper_add_ucast_mac_remote(txn, mac_.c_str(), logical_switch->ovs_entry(), pl_row, dest_ip_.c_str()); SendTrace(UnicastMacRemoteEntry::ADD_REQ); From 052ffa194e7dea0b6014f62dc2ce43af5bb51800 Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Thu, 30 Oct 2014 12:00:55 +0530 Subject: [PATCH 156/218] Fix pagination issue in flow introspect page. FlowKey comparison function does comparison of family now (after merger of IPv6 branch). Initialize FlowKey's family while handling pagination for flow introspect page. Closes-Bug: #1387524 Change-Id: I0951340492b20abb453db4c6f6aa699cea816fc2 --- src/vnsw/agent/pkt/pkt_sandesh_flow.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vnsw/agent/pkt/pkt_sandesh_flow.cc b/src/vnsw/agent/pkt/pkt_sandesh_flow.cc index 374529ea9a7..452ad94b303 100644 --- a/src/vnsw/agent/pkt/pkt_sandesh_flow.cc +++ b/src/vnsw/agent/pkt/pkt_sandesh_flow.cc @@ -282,6 +282,7 @@ bool PktSandeshFlow::SetFlowKey(string key) { // TODO : IPv6 error_code ec; + flow_iteration_key_.family = Address::INET; flow_iteration_key_.src_addr = Ip4Address::from_string(sip.c_str(), ec); flow_iteration_key_.dst_addr = Ip4Address::from_string(dip.c_str(), ec); flow_iteration_key_.protocol = proto; From eff5c187871fc07b370dc6db3adb7838356672b0 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Thu, 30 Oct 2014 14:05:29 +0530 Subject: [PATCH 157/218] Fix wrong reporting of Active state for ToR interfaces ToR interfaces are only logical ones and do not have any corresponding device in the OS. Ignore the link-state and also presence of devices for ToR and VLAN interfaces --- src/vnsw/agent/oper/interface.cc | 25 +++++++++----- src/vnsw/agent/oper/vm_interface.cc | 53 +++++++++++++---------------- src/vnsw/agent/oper/vm_interface.h | 1 + 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 7f05bfadda0..99f8777b3b1 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -634,10 +634,6 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { common_reason += "vn-admin-down "; } - if (vintf->vm() == NULL) { - common_reason += "vm-null "; - } - if (vintf->vrf() == NULL) { common_reason += "vrf-null "; } @@ -647,12 +643,22 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { common_reason += "no-dev "; } - if (vintf->os_oper_state() == false) { - common_reason += "os-state-down "; + if (vintf->NeedDevice()) { + if (vintf->os_index() == Interface::kInvalidIndex) { + common_reason += "no-dev "; + } + + if (vintf->os_oper_state() == false) { + common_reason += "os-state-down "; + } } if (!ipv4_active_) { - string reason = "Inactive< " + common_reason; + if (vintf->layer3_forwarding() == false) { + common_reason += "l3-disabled"; + } + + string reason = "L3 Inactive < " + common_reason; if (vintf->ip_addr().to_ulong() == 0) { reason += "no-ip-addr "; } @@ -661,7 +667,10 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { } if (!l2_active_) { - string reason = "Inactive L2< " + common_reason; + if (vintf->layer2_forwarding() == false) { + common_reason += "l2-disabled"; + } + string reason = "L2 Inactive < " + common_reason; reason += " >"; data.set_l2_active(reason); } diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 94816913f73..fc8cf9d03a6 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -503,29 +503,6 @@ static void ReadDhcpEnable(Agent *agent, VmInterfaceConfigData *data, } } -/* -VmInterface::SubType GetInterfaceSubTypeFromVm(IFMapNode *node) { - for (DBGraphVertex::adjacency_iterator iter = - node->begin(table->GetGraph()); - iter != node->end(table->GetGraph()); ++iter) { - - IFMapNode *adj_node = static_cast(iter.operator->()); - if (agent_->cfg_listener()->SkipNode(adj_node)) { - continue; - } - - if (adj_node->table()->display_name().compare("virtual-machine") == 0) { - return GetInterfaceSubTypeFromVm(adj_node); - } - - if (adj_node->table()->display_name().compare("virtual-router") == 0) { - return VmInterface::TOR; - } - } - return VmInterface::NOVA; -} -*/ - //TBD Use link instead of device_owner VmInterface::SubType GetVmInterfaceSubType(Agent *agent, const std::string &device_owner) { @@ -1514,10 +1491,29 @@ bool VmInterfaceOsOperStateData::OnResync(const InterfaceTable *table, ///////////////////////////////////////////////////////////////////////////// // VM Port Entry utility routines ///////////////////////////////////////////////////////////////////////////// -void VmInterface::GetOsParams(Agent *agent) { - if (subnet_.is_unspecified() && - (rx_vlan_id_ == VmInterface::kInvalidVlanId)) { +// Does the VMInterface need a physical device to be present +bool VmInterface::NeedDevice() const { + bool ret = true; + + if (sub_type_ == TOR) + ret = false; + + if (subnet_.is_unspecified() == false) { + ret = false; + } + + if (rx_vlan_id_ != VmInterface::kInvalidVlanId) { + ret = false; + } else { + // Sanity check. rx_vlan_id is set, make sure tx_vlan_id is also set assert(tx_vlan_id_ == VmInterface::kInvalidVlanId); + } + + return ret; +} + +void VmInterface::GetOsParams(Agent *agent) { + if (NeedDevice()) { Interface::GetOsParams(agent); return; } @@ -1550,9 +1546,8 @@ bool VmInterface::IsActive() const { return false; } - if (rx_vlan_id_ != VmInterface::kInvalidVlanId) { - assert(tx_vlan_id_ != VmInterface::kInvalidVlanId); - return true; + if (NeedDevice() == false) { + return true; } if (subnet_.is_unspecified() && os_index_ == kInvalidIndex) diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index d183b9bd5a8..c25c8aec204 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -386,6 +386,7 @@ class VmInterface : public Interface { void UpdateAllRoutes(); bool IsIpv6Active() const; + bool NeedDevice() const; VmInterface::SubType sub_type() const {return sub_type_;} // Add a vm-interface From fd99469ff02d36484ce6e8d95de6cd9c9e8150aa Mon Sep 17 00:00:00 2001 From: Hari Date: Thu, 30 Oct 2014 02:20:35 -0700 Subject: [PATCH 158/218] Initialize the variables in the constructor - this was causing issues in allowed address pair state machine trigger Change-Id: I394298c8cca7cdc2b967703c422603cc1e3b3298 --- src/vnsw/agent/oper/agent_path.h | 2 +- src/vnsw/agent/oper/vm_interface.cc | 4 ++-- src/vnsw/agent/oper/vm_interface.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index c810ca3ed1c..54cd1edd949 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -28,7 +28,7 @@ class PathPreference { PathPreference(uint32_t sequence, Preference preference, bool wait_for_traffic, bool ecmp): sequence_(sequence), preference_(preference), wait_for_traffic_(wait_for_traffic), - ecmp_(ecmp) {} + ecmp_(ecmp), static_preference_(false) {} uint32_t sequence() const { return sequence_;} Preference preference() const { return preference_;} bool wait_for_traffic() const { diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index fc8cf9d03a6..4b0560b7a81 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -52,7 +52,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : vm_project_uuid_(nil_uuid()), vxlan_id_(0), layer2_forwarding_(true), layer3_forwarding_(true), mac_set_(false), ecmp_(false), tx_vlan_id_(kInvalidVlanId), rx_vlan_id_(kInvalidVlanId), parent_(NULL), - oper_dhcp_options_(), + local_preference_(VmInterface::INVALID), oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), @@ -78,7 +78,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid, vm_project_uuid_(vm_project_uuid), vxlan_id_(0), layer2_forwarding_(true), layer3_forwarding_(true), mac_set_(false), ecmp_(false), tx_vlan_id_(tx_vlan_id), rx_vlan_id_(rx_vlan_id), - parent_(parent), oper_dhcp_options_(), + parent_(parent), local_preference_(VmInterface::INVALID), oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), subnet_(0), diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index c25c8aec204..3617b1339e1 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -696,7 +696,8 @@ struct VmInterfaceConfigData : public VmInterfaceData { vm_uuid_(), vm_name_(), vn_uuid_(), vrf_name_(""), fabric_port_(true), need_linklocal_ip_(false), layer2_forwarding_(true), layer3_forwarding_(true), mirror_enable_(false), ecmp_(false), - dhcp_enable_(true), analyzer_name_(""), oper_dhcp_options_(), + dhcp_enable_(true), analyzer_name_(""), + local_preference_(VmInterface::INVALID), oper_dhcp_options_(), mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), sub_type_(VmInterface::NONE), From 5c2e8203cd2397bae01fd5aebf621035540c180a Mon Sep 17 00:00:00 2001 From: Sachin Bansal Date: Thu, 30 Oct 2014 10:15:47 -0700 Subject: [PATCH 159/218] Few files were still using the term prc_manager instead of device_manager. Fixed that. Change-Id: I8b58544a136aea33971904b5cb81c4b53d45a210 --- src/config/device-manager/contrail-device-manager.conf | 2 +- src/config/device-manager/contrail-device-manager.ini | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config/device-manager/contrail-device-manager.conf b/src/config/device-manager/contrail-device-manager.conf index dd6bcf90702..1d7b07d352d 100644 --- a/src/config/device-manager/contrail-device-manager.conf +++ b/src/config/device-manager/contrail-device-manager.conf @@ -1,5 +1,5 @@ [DEFAULTS] -log_file = /var/log/contrail/contrail-prc-manager.log +log_file = /var/log/contrail/contrail-device-manager.log log_local = 1 log_level = SYS_NOTICE disc_server_ip = 127.0.0.1 diff --git a/src/config/device-manager/contrail-device-manager.ini b/src/config/device-manager/contrail-device-manager.ini index 4293017cca3..b9e64747be2 100644 --- a/src/config/device-manager/contrail-device-manager.ini +++ b/src/config/device-manager/contrail-device-manager.ini @@ -1,12 +1,12 @@ -[program:contrail-prc-manager] -command=/usr/bin/contrail-prc-manager --conf_file /etc/contrail/prc_manager.conf +[program:contrail-device-manager] +command=/usr/bin/contrail-device-manager --conf_file /etc/contrail/device_manager.conf priority=450 autostart=true autorestart=true killasgroup=true stopsignal=KILL redirect_stderr=true -stdout_logfile=/var/log/contrail/contrail-prc-manager-stdout.log +stdout_logfile=/var/log/contrail/contrail-device-manager-stdout.log stderr_logfile=/dev/null exitcodes=0 ; 'expected' exit codes for process (default 0,2) user=contrail From 4345f05d66078936806daeab6aeea86b57812411 Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Thu, 30 Oct 2014 11:45:19 -0700 Subject: [PATCH 160/218] Cleanup a few APIs in mock agent Following changes hasv been implemented: - Pass NextHops parameter as a const reference instead of by value - Remove NextHops and RouteAttribute parameters from delete methods Change-Id: Iecd71053a82cf70404f1c5c726cb919096ad41e6 --- src/bgp/test/xmpp_ecmp_test.cc | 12 +- src/control-node/test/network_agent_mock.cc | 168 ++++++++++---------- src/control-node/test/network_agent_mock.h | 37 +++-- 3 files changed, 103 insertions(+), 114 deletions(-) diff --git a/src/bgp/test/xmpp_ecmp_test.cc b/src/bgp/test/xmpp_ecmp_test.cc index d7447f3e01e..7bb7cdb4614 100644 --- a/src/bgp/test/xmpp_ecmp_test.cc +++ b/src/bgp/test/xmpp_ecmp_test.cc @@ -631,8 +631,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { agent_a_->DeleteRoute(net_1_, "10.0.1.1/32"); } if (enet_) { - agent_a_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32", - nexthops_a); + agent_a_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32"); } } else { agent_a_->SessionDown(); @@ -657,8 +656,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { agent_b_->DeleteRoute(net_2_, "10.0.1.1/32"); } if (enet_) { - agent_b_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32", - nexthops_b); + agent_b_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32"); } } else { agent_b_->SessionDown(); @@ -682,8 +680,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { agent_c_->DeleteRoute(net_1_, "10.0.1.1/32"); } if (enet_) { - agent_c_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32", - nexthops_c); + agent_c_->DeleteEnetRoute(net_1_, "aa:00:00:00:00:0a,10.0.1.1/32"); } } else { agent_c_->SessionDown(); @@ -706,8 +703,7 @@ void XmppEcmpTest::DeleteRoutesAndVerify(bool flap) { agent_d_->DeleteRoute(net_2_, "10.0.1.1/32"); } if (enet_) { - agent_d_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32", - nexthops_d); + agent_d_->DeleteEnetRoute(net_2_, "aa:00:00:00:00:0a,10.0.1.1/32"); } } else { agent_d_->SessionDown(); diff --git a/src/control-node/test/network_agent_mock.cc b/src/control-node/test/network_agent_mock.cc index 64250a3c2a1..def2efee0d1 100644 --- a/src/control-node/test/network_agent_mock.cc +++ b/src/control-node/test/network_agent_mock.cc @@ -266,35 +266,33 @@ pugi::xml_document *XmppDocumentMock::RouteDeleteXmlDoc( pugi::xml_document *XmppDocumentMock::Inet6RouteAddXmlDoc( const std::string &network, const std::string &prefix, - NextHops nexthops, const RouteAttributes &attributes) { + const NextHops &nexthops, const RouteAttributes &attributes) { return Inet6RouteAddDeleteXmlDoc(network, prefix, ADD, nexthops, attributes); } pugi::xml_document *XmppDocumentMock::Inet6RouteChangeXmlDoc( const std::string &network, const std::string &prefix, - NextHops nexthops, const RouteAttributes &attributes) { + const NextHops &nexthops, const RouteAttributes &attributes) { return Inet6RouteAddDeleteXmlDoc(network, prefix, CHANGE, nexthops, attributes); } pugi::xml_document *XmppDocumentMock::Inet6RouteDeleteXmlDoc( - const std::string &network, const std::string &prefix, - NextHops nexthops, const RouteAttributes &attributes) { - return Inet6RouteAddDeleteXmlDoc(network, prefix, DELETE, nexthops, - attributes); + const std::string &network, const std::string &prefix) { + return Inet6RouteAddDeleteXmlDoc(network, prefix, DELETE); } pugi::xml_document *XmppDocumentMock::RouteEnetAddXmlDoc( const std::string &network, const std::string &prefix, NextHops nexthops, const RouteParams *params) { - return RouteEnetAddDeleteXmlDoc(network, prefix, nexthops, params, true); + return RouteEnetAddDeleteXmlDoc(network, prefix, true, nexthops, params); } pugi::xml_document *XmppDocumentMock::RouteEnetDeleteXmlDoc( const std::string &network, const std::string &prefix, NextHops nexthops) { - return RouteEnetAddDeleteXmlDoc(network, prefix, nexthops, NULL, false); + return RouteEnetAddDeleteXmlDoc(network, prefix, false); } pugi::xml_document *XmppDocumentMock::RouteMcastAddXmlDoc( @@ -302,12 +300,12 @@ pugi::xml_document *XmppDocumentMock::RouteMcastAddXmlDoc( const std::string &nexthop, const std::string &label_range, const std::string &encap) { return RouteMcastAddDeleteXmlDoc( - network, sg, nexthop, label_range, encap, true); + network, sg, true, nexthop, label_range, encap); } pugi::xml_document *XmppDocumentMock::RouteMcastDeleteXmlDoc( const std::string &network, const std::string &sg) { - return RouteMcastAddDeleteXmlDoc(network, sg, "", "", "", false); + return RouteMcastAddDeleteXmlDoc(network, sg, false); } @@ -408,7 +406,7 @@ pugi::xml_document *XmppDocumentMock::RouteAddDeleteXmlDoc( pugi::xml_document *XmppDocumentMock::Inet6RouteAddDeleteXmlDoc( const std::string &network, const std::string &prefix, Oper oper, - NextHops nexthops, const RouteAttributes &attributes) { + const NextHops &nexthops, const RouteAttributes &attributes) { xdoc_->reset(); xml_node pubsub = PubSubHeader(kNetworkServiceJID); xml_node pub = pubsub.append_child("publish"); @@ -421,45 +419,51 @@ pugi::xml_document *XmppDocumentMock::Inet6RouteAddDeleteXmlDoc( rt_entry.entry.nlri.af = BgpAf::IPv6; rt_entry.entry.nlri.safi = BgpAf::Unicast; rt_entry.entry.nlri.address = prefix; - rt_entry.entry.local_preference = attributes.local_pref; - rt_entry.entry.sequence_number = attributes.sequence; - if (attributes.sgids.size()) { - rt_entry.entry.security_group_list.security_group = attributes.sgids; - } else { - rt_entry.entry.security_group_list.security_group.push_back(101); - } - - if (nexthops.empty()) { - NextHop nexthop = NextHop(localaddr(), 0); - nexthop.tunnel_encapsulations_.push_back("gre"); - nexthops.push_back(nexthop); - } - - BOOST_FOREACH(NextHop nexthop, nexthops) { - autogen::NextHopType item_nexthop; - item_nexthop.af = BgpAf::IPv4; - assert(!nexthop.address_.empty()); - item_nexthop.address = nexthop.address_; - if (oper == ADD) { - item_nexthop.label = (nexthop.label_ ?: ++label_alloc_); - } else if (oper == CHANGE) { - item_nexthop.label = label_alloc_; - } else if (oper == DELETE) { - item_nexthop.label = 0xFFFFF; + if (oper == ADD || oper == CHANGE) { + rt_entry.entry.local_preference = attributes.local_pref; + rt_entry.entry.sequence_number = attributes.sequence; + if (attributes.sgids.size()) { + rt_entry.entry.security_group_list.security_group = + attributes.sgids; + } else { + rt_entry.entry.security_group_list.security_group.push_back(101); } - item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = - nexthop.tunnel_encapsulations_; - if (nexthop.tunnel_encapsulations_[0] == "all_ipv6") { + + if (nexthops.empty()) { + autogen::NextHopType item_nexthop; + item_nexthop.af = BgpAf::IPv4; + item_nexthop.address = localaddr(); + item_nexthop.label = label_alloc_++; item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. push_back("gre"); - item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. - push_back("udp"); + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); } else { - item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. - push_back(nexthop.tunnel_encapsulations_[0]); + BOOST_FOREACH(NextHop nexthop, nexthops) { + autogen::NextHopType item_nexthop; + + item_nexthop.af = BgpAf::IPv4; + assert(!nexthop.address_.empty()); + item_nexthop.address = nexthop.address_; + if (oper == ADD) { + item_nexthop.label = (nexthop.label_ ?: label_alloc_++); + } else { + item_nexthop.label = label_alloc_; + } + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = + nexthop.tunnel_encapsulations_; + if (nexthop.tunnel_encapsulations_[0] == "all_ipv6") { + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. + push_back("gre"); + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. + push_back("udp"); + } else { + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation. + push_back(nexthop.tunnel_encapsulations_[0]); + } + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + } } - rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); } xml_node item = pub.append_child("item"); @@ -530,8 +534,8 @@ pugi::xml_document *XmppDocumentMock::Inet6RouteAddBogusXmlDoc( } pugi::xml_document *XmppDocumentMock::RouteEnetAddDeleteXmlDoc( - const std::string &network, const std::string &prefix, - NextHops nexthops, const RouteParams *params, bool add) { + const std::string &network, const std::string &prefix, bool add, + const NextHops &nexthops, const RouteParams *params) { xdoc_->reset(); xml_node pubsub = PubSubHeader(kNetworkServiceJID); xml_node pub = pubsub.append_child("publish"); @@ -576,26 +580,32 @@ pugi::xml_document *XmppDocumentMock::RouteEnetAddDeleteXmlDoc( rt_entry.entry.nlri.mac = std::string(mac) ; rt_entry.entry.nlri.address = address ? string(address) : string(); - if (nexthops.empty()) { - NextHop nexthop = NextHop(localaddr(), 0); - nexthop.tunnel_encapsulations_.push_back("gre"); - nexthops.push_back(nexthop); - } - - BOOST_FOREACH(NextHop nexthop, nexthops) { - autogen::EnetNextHopType item_nexthop; - - item_nexthop.af = BgpAf::IPv4; - item_nexthop.address = nexthop.address_; - item_nexthop.label = add ? (nexthop.label_ ?: label_alloc_++) : - 0xFFFFF; - item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = nexthop.tunnel_encapsulations_; - rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); - } + if (add) { + if (nexthops.empty()) { + autogen::EnetNextHopType item_nexthop; + item_nexthop.af = BgpAf::IPv4; + item_nexthop.address = localaddr(); + item_nexthop.label = label_alloc_++; + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = + list_of("gre"); + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + } else { + BOOST_FOREACH(NextHop nexthop, nexthops) { + autogen::EnetNextHopType item_nexthop; + item_nexthop.af = BgpAf::IPv4; + item_nexthop.address = nexthop.address_; + item_nexthop.label = + nexthop.label_ ? nexthop.label_ : label_alloc_++; + item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation = + nexthop.tunnel_encapsulations_; + rt_entry.entry.next_hops.next_hop.push_back(item_nexthop); + } + } - if (params) { - if (params->edge_replication_not_supported) - rt_entry.entry.edge_replication_not_supported = true; + if (params) { + if (params->edge_replication_not_supported) + rt_entry.entry.edge_replication_not_supported = true; + } } xml_node item = pub.append_child("item"); @@ -610,9 +620,9 @@ pugi::xml_document *XmppDocumentMock::RouteEnetAddDeleteXmlDoc( } pugi::xml_document *XmppDocumentMock::RouteMcastAddDeleteXmlDoc( - const std::string &network, const std::string &sg, + const std::string &network, const std::string &sg, bool add, const std::string &nexthop, const std::string &lrange, - const std::string &encap, bool add) { + const std::string &encap) { xdoc_->reset(); string sg_save(sg.c_str()); xml_node pubsub = PubSubHeader(kNetworkServiceJID); @@ -964,15 +974,9 @@ void NetworkAgentMock::ChangeInet6Route(const string &network, } void NetworkAgentMock::DeleteInet6Route(const string &network, - const string &prefix, const string &nexthop, - const RouteAttributes &attributes) { - NextHops nexthops; - if (!nexthop.empty()) { - nexthops.push_back(NextHop(nexthop, 0)); - } + const string &prefix) { AgentPeer *peer = GetAgent(); - xml_document *xdoc = impl_->Inet6RouteDeleteXmlDoc(network, prefix, - nexthops, attributes); + xml_document *xdoc = impl_->Inet6RouteDeleteXmlDoc(network, prefix); peer->SendDocument(xdoc); } @@ -997,16 +1001,6 @@ void NetworkAgentMock::AddEnetRoute(const string &network_name, AddEnetRoute(network_name, prefix, nexthops, params); } -void NetworkAgentMock::DeleteEnetRoute(const string &network_name, - const string &prefix, const string nexthop) { - NextHops nexthops; - - if (!nexthop.empty()) { - nexthops.push_back(NextHop(nexthop, 0)); - } - DeleteEnetRoute(network_name, prefix, nexthops); -} - void NetworkAgentMock::AddEnetRoute(const string &network_name, const string &prefix, NextHops nexthops, const RouteParams *params) { AgentPeer *peer = GetAgent(); @@ -1017,10 +1011,10 @@ void NetworkAgentMock::AddEnetRoute(const string &network_name, } void NetworkAgentMock::DeleteEnetRoute(const string &network_name, - const string &prefix, NextHops nexthops) { + const string &prefix) { AgentPeer *peer = GetAgent(); xml_document *xdoc = - impl_->RouteEnetDeleteXmlDoc(network_name, prefix, nexthops); + impl_->RouteEnetDeleteXmlDoc(network_name, prefix); peer->SendDocument(xdoc); } diff --git a/src/control-node/test/network_agent_mock.h b/src/control-node/test/network_agent_mock.h index c04615cafa8..98a1ae9c256 100644 --- a/src/control-node/test/network_agent_mock.h +++ b/src/control-node/test/network_agent_mock.h @@ -146,14 +146,13 @@ class XmppDocumentMock { const std::string &prefix); pugi::xml_document *Inet6RouteAddXmlDoc(const std::string &network, - const std::string &prefix, NextHops nexthops, + const std::string &prefix, const NextHops &nexthops, const RouteAttributes &attributes); pugi::xml_document *Inet6RouteChangeXmlDoc(const std::string &network, - const std::string &prefix, NextHops nexthops, + const std::string &prefix, const NextHops &nexthops, const RouteAttributes &attributes); pugi::xml_document *Inet6RouteDeleteXmlDoc(const std::string &network, - const std::string &prefix, NextHops nexthops, - const RouteAttributes &attributes); + const std::string &prefix); pugi::xml_document *Inet6RouteAddBogusXmlDoc(const std::string &network, const std::string &prefix, NextHops nexthops, TestErrorType error_type); @@ -186,18 +185,22 @@ class XmppDocumentMock { pugi::xml_document *SubUnsubXmlDoc( const std::string &network, int id, bool sub, std::string type); pugi::xml_document *Inet6RouteAddDeleteXmlDoc(const std::string &network, - const std::string &prefix, Oper oper, NextHops nexthops, - const RouteAttributes &attributes); + const std::string &prefix, Oper oper, + const NextHops &nexthops = NextHops(), + const RouteAttributes &attributes = RouteAttributes()); pugi::xml_document *RouteAddDeleteXmlDoc(const std::string &network, const std::string &prefix, bool add, const NextHops &nexthop = NextHops(), const RouteAttributes &attributes = RouteAttributes()); pugi::xml_document *RouteEnetAddDeleteXmlDoc(const std::string &network, - const std::string &prefix, NextHops nexthop, - const RouteParams *params, bool add); + const std::string &prefix, bool add, + const NextHops &nexthops = NextHops(), + const RouteParams *params = NULL); pugi::xml_document *RouteMcastAddDeleteXmlDoc(const std::string &network, - const std::string &sg, const std::string &nexthop, - const std::string &label_range, const std::string &encap, bool add); + const std::string &sg, bool add, + const std::string &nexthop = std::string(), + const std::string &label_range = std::string(), + const std::string &encap = std::string()); std::string hostname_; int label_alloc_; @@ -329,14 +332,13 @@ class NetworkAgentMock { void DeleteRoute(const std::string &network, const std::string &prefix); void AddInet6Route(const std::string &network, const std::string &prefix, - const NextHops &nexthops, + const NextHops &nexthops = NextHops(), const RouteAttributes &attributes = RouteAttributes()); void ChangeInet6Route(const std::string &network, const std::string &prefix, - const NextHops &nexthops, - const RouteAttributes &attributes = RouteAttributes()); - void DeleteInet6Route(const std::string &network, const std::string &prefix, - const std::string &nexthop = "", + const NextHops &nexthops = NextHops(), const RouteAttributes &attributes = RouteAttributes()); + void DeleteInet6Route(const std::string &network, + const std::string &prefix); void AddBogusInet6Route(const std::string &network, const std::string &prefix, const std::string &nexthop, TestErrorType error_type); @@ -360,12 +362,9 @@ class NetworkAgentMock { void AddEnetRoute(const std::string &network, const std::string &prefix, const std::string nexthop = "", const RouteParams *params = NULL); - void DeleteEnetRoute(const std::string &network, const std::string &prefix, - const std::string nexthop = ""); void AddEnetRoute(const std::string &network, const std::string &prefix, NextHops nexthops, const RouteParams *params = NULL); - void DeleteEnetRoute(const std::string &network, const std::string &prefix, - NextHops nexthops); + void DeleteEnetRoute(const std::string &network, const std::string &prefix); void McastSubscribe(const std::string &network, int id = -1, bool wait_for_established = true) { From 3b6e6f06739c2ddf2b887c6fb14cd3f873faf02d Mon Sep 17 00:00:00 2001 From: Praneet Bachheti Date: Thu, 30 Oct 2014 16:55:12 -0700 Subject: [PATCH 161/218] raise SecurityGroupCannotRemoveDefault only if not admin Change-Id: I518a3baf9e5d19507878ac9daa46f1d29d3c60d1 Closes-Bug: 1387904 --- src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py | 4 ++-- .../vnc_openstack/vnc_openstack/neutron_plugin_interface.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 534b37a9b3c..5e7e20ef198 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -3670,10 +3670,10 @@ def security_group_read(self, sg_id): return self._security_group_vnc_to_neutron(sg_obj) #end security_group_read - def security_group_delete(self, sg_id): + def security_group_delete(self, context, sg_id): try: sg_obj = self._vnc_lib.security_group_read(id=sg_id) - if sg_obj.name == 'default': + if sg_obj.name == 'default' and not context['is_admin']: self._raise_contrail_exception( 'SecurityGroupCannotRemoveDefault') except NoIdError: diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_interface.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_interface.py index 3ad085486c3..5dbc9d6cd3e 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_interface.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_interface.py @@ -632,7 +632,7 @@ def plugin_delete_sec_group(self, context, sg): try: cfgdb = self._get_user_cfgdb(context) - cfgdb.security_group_delete(sg['id']) + cfgdb.security_group_delete(context, sg['id']) LOG.debug("plugin_delete_sec_group(): " + pformat(sg['id'])) except Exception as e: cgitb.Hook(format="text").handle(sys.exc_info()) From 3b2960ba88e2cfd2da78c07e423015c5c318dbd2 Mon Sep 17 00:00:00 2001 From: Ignatious Johnson Date: Mon, 27 Oct 2014 16:28:45 -0700 Subject: [PATCH 162/218] Ignore 503 Service Unavailable, any api call will connect to api-server, if not connected. VncApi should ignore 503 Service Unavailable and continue as any call to VncAPi will reconnect to api-server, if not connected, else on reboot of the nodes, neutron server fails to comeup Change-Id: I67e02fab08469a05f9708fc8d3f1e6b08eda290e Closes-Bug: 1379640 --- src/api-lib/vnc_api.py | 27 ++++++++++++++++++++++----- src/config/common/exceptions.py | 10 ++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/api-lib/vnc_api.py b/src/api-lib/vnc_api.py index 369b0072bed..3e7ad03276f 100644 --- a/src/api-lib/vnc_api.py +++ b/src/api-lib/vnc_api.py @@ -177,9 +177,15 @@ def __init__(self, username=None, password=None, tenant_name=None, self._create_api_server_session() - homepage = self._request_server(rest.OP_GET, self._base_url, - retry_on_error=False) - self._cfg_root_url = self._parse_homepage(homepage) + try: + homepage = self._request(rest.OP_GET, self._base_url, + retry_on_error=False) + self._cfg_root_url = self._parse_homepage(homepage) + except ServiceUnavailableError as e: + # Ignore http.code 503 here. + # _request_server will reconnect during requests + logger = logging.getLogger(__name__) + logger.warn("Exception: %s", str(e)) #end __init__ def _obj_serializer_diff(self, obj): @@ -326,6 +332,17 @@ def _read_args_to_id(self, obj_type, fq_name=None, fq_name_str=None, def _request_server(self, op, url, data=None, retry_on_error=True, retry_after_authn=False, retry_count=30): + if not hasattr(self, '_cfg_root_url'): + homepage = self._request(rest.OP_GET, self._base_url, + retry_on_error=False) + self._cfg_root_url = self._parse_homepage(homepage) + + return self._request(op, url, data=data, retry_on_error=retry_on_error, + retry_after_authn=retry_after_authn, + retry_count=retry_count) + + def _request(self, op, url, data=None, retry_on_error=True, + retry_after_authn=False, retry_count=30): retried = 0 while True: try: @@ -358,7 +375,7 @@ def _request_server(self, op, url, data=None, retry_on_error=True, if ((status == 401) and (not self._auth_token_input) and (not retry_after_authn)): self._headers = self._authenticate(content, self._headers) # Recursive call after authentication (max 1 level) - content = self._request_server(op, url, data=data, retry_after_authn=True) + content = self._request(op, url, data=data, retry_after_authn=True) return content elif status == 404: @@ -373,7 +390,7 @@ def _request_server(self, op, url, data=None, retry_on_error=True, elif status == 503: retried += 1 if retried >= retry_count: - raise TimeOutError('Service Unavailable Timeout 503') + raise ServiceUnavailableError('Service Unavailable Timeout 503') time.sleep(1) continue diff --git a/src/config/common/exceptions.py b/src/config/common/exceptions.py index 8d5f1d98b35..bfcb3ed8600 100644 --- a/src/config/common/exceptions.py +++ b/src/config/common/exceptions.py @@ -8,6 +8,16 @@ class VncError(Exception): pass # end class VncError +class ServiceUnavailableError(VncError): + def __init__(self, code): + self._reason_code = code + # end __init__ + + def __str__(self): + return 'Service unavailable time out due to: %s' % (str(self._reason_code)) + # end __str__ +# end class ServiceUnavailableError + class TimeOutError(VncError): def __init__(self, code): self._reason_code = code From 672bc01541199a37b13de9f95f02f77688dbe33a Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Fri, 31 Oct 2014 05:38:44 -0700 Subject: [PATCH 163/218] add logic to wait for vn to be present before eporting routes. --- .../ovs_tor_agent/ovsdb_client/ovsdb_entry.h | 6 +- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 102 ++++++++++++++---- .../ovsdb_client/unicast_mac_local_ovsdb.h | 31 +++++- 3 files changed, 113 insertions(+), 26 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h index 4630a32bed3..df700bf6ed9 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h @@ -27,9 +27,9 @@ class OvsdbEntry : public KSyncEntry, public OvsdbEntryBase { OvsdbEntry(OvsdbObject *table, uint32_t index); virtual ~OvsdbEntry(); - bool Add(); - bool Change(); - bool Delete(); + virtual bool Add(); + virtual bool Change(); + virtual bool Delete(); struct ovsdb_idl_row *ovs_entry() {return ovs_entry_;} KSyncObject* GetObject(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index 6f955c2f454..f81353aa71c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -10,14 +10,73 @@ extern "C" { #include #include #include +#include #include using OVSDB::UnicastMacLocalOvsdb; +using OVSDB::UnicastMacLocalEntry; using std::string; +UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, + const UnicastMacLocalEntry *key) : OvsdbEntry(table), mac_(key->mac_), + logical_switch_name_(key->logical_switch_name_), dest_ip_(key->dest_ip_) { + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry l_key(l_table, logical_switch_name_.c_str()); + logical_switch_ = l_table->GetReference(&l_key); +} + +UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, + struct ovsdb_idl_row *row) : OvsdbEntry(table), + mac_(ovsdb_wrapper_ucast_mac_local_mac(row)), + logical_switch_name_(ovsdb_wrapper_ucast_mac_local_logical_switch(row)), + dest_ip_(ovsdb_wrapper_ucast_mac_local_dst_ip(row)) { +} + +UnicastMacLocalEntry::~UnicastMacLocalEntry() { +} + +bool UnicastMacLocalEntry::Add() { + UnicastMacLocalOvsdb *table = static_cast(table_); + OVSDB_TRACE(Trace, "Adding Route " + mac_ + " VN uuid " + + logical_switch_name_ + " destination IP " + dest_ip_); + boost::uuids::uuid ls_uuid = StringToUuid(logical_switch_name_); + boost::system::error_code err; + Ip4Address dest = Ip4Address::from_string(dest_ip_, err); + table->peer()->AddOvsRoute(ls_uuid, MacAddress(mac_), dest); + return true; +} + +bool UnicastMacLocalEntry::Delete() { + UnicastMacLocalOvsdb *table = static_cast(table_); + OVSDB_TRACE(Trace, "Deleting Route " + mac_ + " VN uuid " + + logical_switch_name_ + " destination IP " + dest_ip_); + boost::uuids::uuid ls_uuid = StringToUuid(logical_switch_name_); + table->peer()->DeleteOvsRoute(ls_uuid, MacAddress(mac_)); + return true; +} + +bool UnicastMacLocalEntry::IsLess(const KSyncEntry& entry) const { + const UnicastMacLocalEntry &ucast = + static_cast(entry); + if (mac_ != ucast.mac_) + return mac_ < ucast.mac_; + return logical_switch_name_ < ucast.logical_switch_name_; +} + +KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() { + LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *l_switch = + static_cast(l_table->GetReference(&key)); + if (!l_switch->IsResolved()) { + return l_switch; + } + return NULL; +} + UnicastMacLocalOvsdb::UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer) : - client_idl_(idl), peer_(peer) { - client_idl_->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, + OvsdbObject(idl), peer_(peer) { + idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, boost::bind(&UnicastMacLocalOvsdb::Notify, this, _1, _2)); } @@ -25,36 +84,39 @@ UnicastMacLocalOvsdb::~UnicastMacLocalOvsdb() { client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL); } +OvsPeer *UnicastMacLocalOvsdb::peer() { + return peer_; +} + void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row); - const char *mac_str = ovsdb_wrapper_ucast_mac_local_mac(row); const char *dest_ip = ovsdb_wrapper_ucast_mac_local_dst_ip(row); /* ignore if ls_name is not present */ if (ls_name == NULL) { return; } - boost::uuids::uuid ls_uuid = StringToUuid(ls_name); - MacAddress mac(mac_str); - Ip4Address dest; + UnicastMacLocalEntry key(this, row); + UnicastMacLocalEntry *entry = + static_cast(Find(&key)); /* trigger delete if dest ip is not available */ - bool delete_entry = true; - if (dest_ip != NULL) { - delete_entry = false; - boost::system::error_code err; - dest = Ip4Address::from_string(dest_ip, err); - } - if (op == OvsdbClientIdl::OVSDB_DEL || delete_entry) { - OVSDB_TRACE(Trace, string("Deleting Route ") + string(mac_str) + - string(" VN uuid ") + string(ls_name)); - peer_->DeleteOvsRoute(ls_uuid, mac); + if (op == OvsdbClientIdl::OVSDB_DEL || dest_ip == NULL) { + if (entry != NULL) { + Delete(entry); + } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - OVSDB_TRACE(Trace, string("Adding Route ") + string(mac_str) + - string(" VN uuid ") + string(ls_name) + - string(" destination IP ") + string(dest_ip)); - peer_->AddOvsRoute(ls_uuid, mac, dest); + if (entry == NULL) { + entry = static_cast(Create(&key)); + } } else { assert(0); } } +KSyncEntry *UnicastMacLocalOvsdb::Alloc(const KSyncEntry *key, uint32_t index) { + const UnicastMacLocalEntry *k_entry = + static_cast(key); + UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, k_entry); + return entry; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h index f49126e0fad..98b1d0d7d90 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h @@ -5,22 +5,47 @@ #ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ #define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ -#include +#include +#include class OvsPeer; namespace OVSDB { -class UnicastMacLocalOvsdb { +class UnicastMacLocalOvsdb : public OvsdbObject { public: UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer); ~UnicastMacLocalOvsdb(); + OvsPeer *peer(); void Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); private: - OvsdbClientIdl *client_idl_; OvsPeer *peer_; DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalOvsdb); }; + +class UnicastMacLocalEntry : public OvsdbEntry { +public: + UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, + const UnicastMacLocalEntry *key); + UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, + struct ovsdb_idl_row *row); + ~UnicastMacLocalEntry(); + + bool Add(); + bool Delete(); + bool IsLess(const KSyncEntry&) const; + KSyncEntry* UnresolvedReference(); + std::string ToString() const {return "Unicast Mac Local";} +private: + friend class UnicastMacLocalOvsdb; + std::string mac_; + std::string logical_switch_name_; + std::string dest_ip_; + KSyncEntryPtr logical_switch_; + DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalEntry); +}; + }; #endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_ROUTE_H_ From dbe61d68cab01158d85b6a539079877fcdbffec7 Mon Sep 17 00:00:00 2001 From: Hari Date: Fri, 31 Oct 2014 22:10:03 -0700 Subject: [PATCH 164/218] move the address creation for service node from neutron plugin to api vns address management --- src/config/api-server/vnc_addr_mgmt.py | 64 +++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/config/api-server/vnc_addr_mgmt.py b/src/config/api-server/vnc_addr_mgmt.py index c7b98948906..51249b9308c 100644 --- a/src/config/api-server/vnc_addr_mgmt.py +++ b/src/config/api-server/vnc_addr_mgmt.py @@ -119,6 +119,20 @@ def __str__(self): # end AddrMgmtInvalidGatewayIp +class AddrMgmtInvalidServiceNodeIp(AddrMgmtError): + + def __init__(self, subnet_val, service_address): + self.subnet_val = subnet_val + self.service_address = service_address + # end __init__ + + def __str__(self): + return "subnet(%s) has Invalid Service Node ip address(%s)" %\ + (self.subnet_val, self.service_address) + # end __str__ +# end AddrMgmtInvalidServiceNodeIp + + class AddrMgmtInvalidDnsNameServer(AddrMgmtError): def __init__(self, subnet_val, name_server): @@ -152,7 +166,7 @@ def set_db_conn(cls, db_conn): # end set_db_conn def __init__(self, name, prefix, prefix_len, - gw=None, enable_dhcp=True, + gw=None, service_address=None, enable_dhcp=True, dns_nameservers=None, alloc_pool_list=None, addr_from_start=False): @@ -184,6 +198,20 @@ def __init__(self, name, prefix, prefix_len, else: gw_ip = IPAddress(network.last - 1) + # check service_address + if service_address: + try: + service_node_address = IPAddress(service_address) + except AddrFormatError: + raise AddrMgmtInvalidServiceNodeIp(name, service_node_address) + + else: + # reserve a service address ip in subnet + if addr_from_start: + service_node_address = IPAddress(network.first + 2) + else: + service_node_address = IPAddress(network.last - 2) + # check dns_nameservers for nameserver in dns_nameservers or []: try: @@ -208,11 +236,12 @@ def __init__(self, name, prefix, prefix_len, 'end':int(IPAddress(alloc_pool['end']))} alloc_int_list.append(alloc_int) - # exclude gw_ip if it is within allocation-pool + # exclude gw_ip, service_node_address if they are within allocation-pool for alloc_int in alloc_int_list: if alloc_int['start'] <= int(gw_ip) <= alloc_int['end']: exclude.append(gw_ip) - break + if alloc_int['start'] <= int(service_node_address) <= alloc_int['end']: + exclude.append(service_node_address) self._db_conn.subnet_create_allocator(name, alloc_int_list, addr_from_start) @@ -225,6 +254,7 @@ def __init__(self, name, prefix, prefix_len, self._version = network.version self._exclude = exclude self.gw_ip = gw_ip + self.dns_server_address = service_node_address self._alloc_pool_list = alloc_pool_list self.enable_dhcp = enable_dhcp self.dns_nameservers = dns_nameservers @@ -344,6 +374,7 @@ def _get_subnet_dicts(self, vn_fq_name, vn_dict=None): for ipam_subnet in ipam_subnets: subnet_dict = copy.deepcopy(ipam_subnet['subnet']) subnet_dict['gw'] = ipam_subnet.get('default_gateway', None) + subnet_dict['dns_server_address'] = ipam_subnet.get('dns_server_address', None) subnet_dict['allocation_pools'] = \ ipam_subnet.get('allocation_pools', None) subnet_dict['enable_dhcp'] = ipam_subnet.get('enable_dhcp', True) @@ -372,6 +403,7 @@ def _create_subnet_objs(self, vn_fq_name_str, vn_dict): subnet['ip_prefix_len']) gateway_ip = ipam_subnet.get('default_gateway', None) + service_address = ipam_subnet.get('dns_server_address', None) allocation_pools = ipam_subnet.get('allocation_pools', None) dhcp_config = ipam_subnet.get('enable_dhcp', True) nameservers = ipam_subnet.get('dns_nameservers', None) @@ -379,13 +411,15 @@ def _create_subnet_objs(self, vn_fq_name_str, vn_dict): subnet_obj = Subnet( '%s:%s' % (vn_fq_name_str, subnet_name), subnet['ip_prefix'], str(subnet['ip_prefix_len']), - gw=gateway_ip, enable_dhcp=dhcp_config, + gw=gateway_ip, service_address=service_address, + enable_dhcp=dhcp_config, dns_nameservers=nameservers, alloc_pool_list=allocation_pools, addr_from_start=addr_start) self._subnet_objs[vn_fq_name_str][subnet_name] = \ subnet_obj ipam_subnet['default_gateway'] = str(subnet_obj.gw_ip) + ipam_subnet['dns_server_address'] = str(subnet_obj.dns_server_address) # end _create_subnet_objs def config_log(self, msg, level): @@ -436,8 +470,8 @@ def net_update_req(self, vn_fq_name, db_vn_dict, req_vn_dict, obj_uuid=None): # check db_subnet_dicts and req_subnet_dicts # following parameters are same for subnets present in both dicts - # 1. enable_dhcp, 2. default_gateway, 3. allocation_pool - # 4 dns_nameservers + # 1. enable_dhcp, 2. default_gateway, 3. dns_server_address + # 4. allocation_pool, 5. dns_nameservers for key in req_subnet_dicts.keys(): req_subnet = req_subnet_dicts[key] if key in db_subnet_dicts.keys(): @@ -446,6 +480,8 @@ def net_update_req(self, vn_fq_name, db_vn_dict, req_vn_dict, obj_uuid=None): req_subnet['enable_dhcp'] = True if (req_subnet['gw'] != db_subnet['gw']): raise AddrMgmtSubnetInvalid(vn_fq_name_str, key) + if (req_subnet['dns_server_address'] != db_subnet['dns_server_address']): + raise AddrMgmtSubnetInvalid(vn_fq_name_str, key) req_alloc_list = req_subnet['allocation_pools'] or [] db_alloc_list = db_subnet['allocation_pools'] or [] @@ -641,6 +677,16 @@ def net_check_subnet(self, db_vn_dict, req_vn_dict): err_msg = "gateway Ip of configured subnets conflicting " \ "in deciding forwarding mode for virtual network." return False, err_msg + + # check service address + service_address = ipam_subnet.get('dns_server_address', None) + if service_address is not None: + try: + service_node_address = IPAddress(service_address) + except AddrFormatError: + err_msg = "Invalid Dns Server Ip address:%s" \ + %(service_address) + return False, err_msg return True, "" # end net_check_subnet @@ -747,6 +793,7 @@ def ip_alloc_req(self, vn_fq_name, sub=None, asked_ip_addr=None, subnet_dict['ip_prefix'], subnet_dict['ip_prefix_len'], gw=subnet_dict['gw'], + service_address=subnet_dict['dns_server_address'], enable_dhcp=subnet_dict['enable_dhcp'], dns_nameservers=subnet_dict['dns_nameservers'], alloc_pool_list=subnet_dict['allocation_pools'], @@ -757,6 +804,8 @@ def ip_alloc_req(self, vn_fq_name, sub=None, asked_ip_addr=None, continue if asked_ip_addr == str(subnet_obj.gw_ip): return asked_ip_addr + if asked_ip_addr == str(subnet_obj.dns_server_address): + return asked_ip_addr if asked_ip_addr and not subnet_obj.ip_belongs(asked_ip_addr): continue try: @@ -792,6 +841,7 @@ def ip_alloc_notify(self, ip_addr, vn_fq_name): subnet_dict['ip_prefix'], subnet_dict['ip_prefix_len'], gw=subnet_dict['gw'], + service_address=subnet_dict['dns_server_address'], enable_dhcp=subnet_dict['enable_dhcp'], dns_nameservers=subnet_dict['dns_nameservers'], alloc_pool_list=subnet_dict['allocation_pools'], @@ -827,6 +877,7 @@ def ip_free_req(self, ip_addr, vn_fq_name, sub=None): subnet_dict['ip_prefix'], subnet_dict['ip_prefix_len'], gw=subnet_dict['gw'], + service_address=subnet_dict['dns_server_address'], enable_dhcp=subnet_dict['enable_dhcp'], dns_nameservers=subnet_dict['dns_nameservers'], alloc_pool_list=subnet_dict['allocation_pools'], @@ -861,6 +912,7 @@ def is_ip_allocated(self, ip_addr, vn_fq_name, sub=None): subnet_dict['ip_prefix'], subnet_dict['ip_prefix_len'], gw=subnet_dict['gw'], + service_address=subnet_dict['dns_server_address'], enable_dhcp=subnet_dict['enable_dhcp'], dns_nameservers=subnet_dict['dns_nameservers'], alloc_pool_list=subnet_dict['allocation_pools'], From 5fefb09bddc64fa865d58997aceb8038097e8a94 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Fri, 31 Oct 2014 14:37:18 +0530 Subject: [PATCH 165/218] Fix#1: L2 multicast route not getting deleted. When VRF delete is issued, agent unsubscribes from VRF and issues a walk to clear all externally(BGP peer) created paths to be deleted. For L2 multicast fabric tree path, the peer is MULTICAST_TREE_BUILDER. This was not getting deleted. So multicast route used to retain the same resulting in VRF not getting deleted. Previous to EVPN code it used to work as multicast route had only one path and on VRF delete it used to be flushed, however EVPN brings in path in multicast route for every composite NH created for replication. Fix#2: Parsing of ethernet tag and mac address in retract message Reference https://github.com/manishsing/contrail-controller/commit/5d097d9000de0c91bdbad67c8bb52db061e3f0a8 Change-Id: I97583ebefdcf647276b13fdd70893709ccba7fc9 Closes-Bug: 1386924 --- src/vnsw/agent/controller/controller_peer.cc | 9 ++- src/vnsw/agent/oper/agent_route.cc | 3 + src/vnsw/agent/test/test_xmpp.cc | 2 +- src/vnsw/agent/test/test_xmpp_bcast.cc | 61 ++++++++++++++++++-- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index 76ff1a26c26..d76f927df5e 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -129,7 +129,14 @@ void AgentXmppChannel::ReceiveEvpnUpdate(XmlPugi *pugi) { char *mac_str = strtok_r(buff + offset, "-", &saveptr); uint32_t ethernet_tag = 0; - if (mac_str) { + //retract id expected are: + //00:00:00:01:01:01,1.1.1.1 - Mac and IP + //10-00:00:00:01:01:01,1.1.1.1 - Ehernet tag, mac, ip. + //In case of not finding pattern "-" whole string will be + //returned in mac_str. So dont use it for ethernet_tag. + //Check for string length of saveptr to know if string was + //tokenised. + if ((strlen(saveptr) != 0) && mac_str) { ethernet_tag = atoi(mac_str); offset += strlen(mac_str) + 1; } diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index 0bc75c2c9bf..eba83b59227 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -125,6 +125,9 @@ bool AgentRouteTable::DeleteAllBgpPath(DBTablePartBase *part, if (peer && peer->GetType() == Peer::BGP_PEER) { DeletePathFromPeer(part, route, path); } + if (peer && peer->GetType() == Peer::MULTICAST_FABRIC_TREE_BUILDER) { + DeletePathFromPeer(part, route, path); + } } } return true; diff --git a/src/vnsw/agent/test/test_xmpp.cc b/src/vnsw/agent/test/test_xmpp.cc index 45f53b2b030..2c93b214346 100644 --- a/src/vnsw/agent/test/test_xmpp.cc +++ b/src/vnsw/agent/test/test_xmpp.cc @@ -485,7 +485,7 @@ TEST_F(AgentXmppUnitTest, Connection) { InetUnicastRouteEntry *rt = RouteGet("vrf1", addr, 32); EXPECT_STREQ(rt->dest_vn_name().c_str(), "vn1"); - MacAddress mac("00:00:00:01:01:01"); + MacAddress mac("0:0:0:1:1:1"); EXPECT_TRUE(L2RouteFind("vrf1", mac)); // Send route, back to vrf1 diff --git a/src/vnsw/agent/test/test_xmpp_bcast.cc b/src/vnsw/agent/test/test_xmpp_bcast.cc index 16c38b2ae3b..9bce47598fc 100644 --- a/src/vnsw/agent/test/test_xmpp_bcast.cc +++ b/src/vnsw/agent/test/test_xmpp_bcast.cc @@ -128,9 +128,9 @@ class ControlNodeMockBgpXmppPeer { autogen::EnetItemType enet_item; enet_item.Clear(); if (enet_item.XmlParse(item)) { - if (enet_item.entry.nlri.mac == "0:0:0:1:1:1") + if (enet_item.entry.nlri.mac == "00:00:00:01:01:01") l2_route_1_seen_ = true; - if (enet_item.entry.nlri.mac == "0:0:0:2:2:2") + if (enet_item.entry.nlri.mac == "00:00:00:02:02:02") l2_route_2_seen_ = true; if (enet_item.entry.nlri.mac == "ff:ff:ff:ff:ff:ff") @@ -730,8 +730,9 @@ class AgentXmppUnitTest : public ::testing::Test { client->WaitForIdle(); client->Reset(); DeleteVmportEnv(input, 2, 1, 0); - WAIT_FOR(1000, 1000, + WAIT_FOR(1000, 10000, (Agent::GetInstance()->vrf_table()->Size() == 1)); + cout << "XMPP BCAST " << Agent::GetInstance()->vrf_table()->Size() << endl; #if 0 TaskScheduler::GetInstance()->Stop(); @@ -1366,13 +1367,14 @@ TEST_F(AgentXmppUnitTest, Test_Olist_change) { SendBcastRouteMessage(mock_peer.get(), "vrf1", "255.255.255.255", alloc_label+1, "127.0.0.1", alloc_label + 17); + // Bcast Route with updated olist + WAIT_FOR(1000, 10000, (bgp_peer.get()->Count() == 4)); + WAIT_FOR(1000, 10000, (client->CompositeNHCount() == 3)); + nh = const_cast(rt_m->GetActiveNextHop()); ASSERT_TRUE(nh != NULL); ASSERT_TRUE(nh->GetType() == NextHop::COMPOSITE); cnh = static_cast(nh); - // Bcast Route with updated olist - WAIT_FOR(1000, 10000, (bgp_peer.get()->Count() == 4)); - WAIT_FOR(1000, 10000, (client->CompositeNHCount() == 5)); client->CompositeNHWait(11); client->MplsWait(5); @@ -1518,6 +1520,53 @@ TEST_F(AgentXmppUnitTest, Test_Olist_change_with_same_label) { client->WaitForIdle(5); } +/* + * Add VRF, Add VM and then send fabric olist for multicast route. + * Now delete VRF and VM. This should delete multicast route without + * any retract message from control. + */ +TEST_F(AgentXmppUnitTest, multicast_fabric_path_delete_on_vrf_delete) { + client->Reset(); + client->WaitForIdle(); + + XmppConnectionSetUp(true); + + int alloc_label = GetStartLabel(); + //Verify all-broadcast + Layer2RouteEntry *rt_m = GetL2FloodRoute("vrf1"); + ASSERT_TRUE(rt_m != NULL); + NextHop *nh = const_cast(rt_m->GetActiveNextHop()); + ASSERT_TRUE(nh != NULL); + ASSERT_TRUE(nh->GetType() == NextHop::COMPOSITE); + + //Send fabric tree, and dont delete + SendBcastRouteMessage(mock_peer.get(), "vrf1", + "255.255.255.255", alloc_label, + "127.0.0.1", + alloc_label + 1, + alloc_label + 2); + WAIT_FOR(1000, 10000, (rt_m->GetPathList().size() == 3)); + + IntfCfgDel(input, 0); + client->WaitForIdle(); + IntfCfgDel(input, 1); + client->WaitForIdle(); + VrfDelReq("vrf1"); + client->WaitForIdle(); + + //Flood route should be deleted bcoz all local VM are gone, + //VRF is marked for delete and should have internally + //triggered deletion of paths by external peers. + rt_m = GetL2FloodRoute("vrf1"); + ASSERT_TRUE(rt_m == NULL); + + XmppSubnetTearDown(); + client->WaitForIdle(5); + + xc->ConfigUpdate(new XmppConfigData()); + client->WaitForIdle(5); +} + TEST_F(AgentXmppUnitTest, SubnetBcast_Retract_from_non_mcast_tree_builder) { Agent::GetInstance()->set_controller_ifmap_xmpp_server("127.0.0.2", 1); From 0a6680ee4163919b18c5c5307bce97eb844f0d47 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Wed, 29 Oct 2014 16:43:12 +0530 Subject: [PATCH 166/218] In case of VMWare, set promiscous mode for ethernet port connecting to VM In VMWare, we have a physical-port connecting to vmware-port-group vswitch. For Layer2 mode to work, this port must be set in promiscous mode. Otherwise, packets to be bridged will get filtered in MAC. Add a sub-type for physical-ports. Promiscous mode is set only for interfaces of type VMWARE. Change-Id: Ib9ff179af41de77debcc5a5459b531974838a830 --- src/vnsw/agent/init/contrail_init_common.cc | 6 ++- src/vnsw/agent/init/test/test_vmware.cc | 1 + src/vnsw/agent/ksync/interface_ksync.cc | 7 +++ src/vnsw/agent/ksync/interface_ksync.h | 1 + src/vnsw/agent/oper/interface.cc | 53 +++++++++++++++++---- src/vnsw/agent/oper/physical_interface.h | 22 ++++++--- src/vnsw/agent/oper/test/SConscript | 2 +- src/vnsw/agent/pkt/test/test_flowtable.cc | 2 +- src/vnsw/agent/pkt/test/test_pkt.cc | 2 +- src/vnsw/agent/pkt/test/test_pkt_flow.cc | 2 +- src/vnsw/agent/test/test_fip_cfg.cc | 2 +- src/vnsw/agent/test/test_l2route.cc | 3 +- src/vnsw/agent/test/test_mirror.cc | 3 +- src/vnsw/agent/test/test_route.cc | 2 +- src/vnsw/agent/test/test_vmport_cfg.cc | 20 +++++++- 15 files changed, 100 insertions(+), 28 deletions(-) diff --git a/src/vnsw/agent/init/contrail_init_common.cc b/src/vnsw/agent/init/contrail_init_common.cc index b7d911fc7ab..612f535a150 100644 --- a/src/vnsw/agent/init/contrail_init_common.cc +++ b/src/vnsw/agent/init/contrail_init_common.cc @@ -121,7 +121,8 @@ void ContrailInitCommon::CreateInterfaces() { InterfaceTable *table = agent()->interface_table(); PhysicalInterface::Create(table, agent_param()->eth_port(), - agent()->fabric_vrf_name(), false); + agent()->fabric_vrf_name(), + PhysicalInterface::FABRIC); InetInterface::Create(table, agent_param()->vhost_name(), InetInterface::VHOST, agent()->fabric_vrf_name(), agent_param()->vhost_addr(), @@ -133,7 +134,8 @@ void ContrailInitCommon::CreateInterfaces() { if (agent_param()->isVmwareMode()) { PhysicalInterface::Create(agent()->interface_table(), agent_param()->vmware_physical_port(), - agent()->fabric_vrf_name(), true); + agent()->fabric_vrf_name(), + PhysicalInterface::VMWARE); } InetInterfaceKey key(agent()->vhost_interface_name()); diff --git a/src/vnsw/agent/init/test/test_vmware.cc b/src/vnsw/agent/init/test/test_vmware.cc index f481079baf5..54deae8633e 100644 --- a/src/vnsw/agent/init/test/test_vmware.cc +++ b/src/vnsw/agent/init/test/test_vmware.cc @@ -63,6 +63,7 @@ TEST_F(VmwareTest, VmwarePhysicalPort_1) { PhysicalInterface *phy_intf = static_cast(intf); EXPECT_TRUE(phy_intf->persistent() == true); + EXPECT_TRUE(phy_intf->subtype() == PhysicalInterface::VMWARE); PhysicalInterfaceKey key1(agent->fabric_interface_name()); intf = static_cast diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 3e96fcf571a..1b677dd3488 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -64,6 +64,7 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, tx_vlan_id_(entry->tx_vlan_id_), vrf_id_(entry->vrf_id_), persistent_(entry->persistent_), + subtype_(entry->subtype_), xconnect_(entry->xconnect_) { } @@ -96,6 +97,7 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, tx_vlan_id_(VmInterface::kInvalidVlanId), vrf_id_(intf->vrf_id()), persistent_(false), + subtype_(PhysicalInterface::INVALID), xconnect_(NULL) { if (intf->flow_key_nh()) { @@ -291,6 +293,7 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { dmac = intf->mac(); PhysicalInterface *phy_intf = static_cast(intf); persistent_ = phy_intf->persistent(); + subtype_ = phy_intf->subtype(); break; } case Interface::INET: @@ -429,6 +432,10 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { if (!persistent_) { flags |= VIF_FLAG_VHOST_PHYS; } + + if (subtype_ == PhysicalInterface::VMWARE) { + flags |= VIF_FLAG_PROMISCOUS; + } break; } diff --git a/src/vnsw/agent/ksync/interface_ksync.h b/src/vnsw/agent/ksync/interface_ksync.h index c578c2a5295..7222e074c52 100644 --- a/src/vnsw/agent/ksync/interface_ksync.h +++ b/src/vnsw/agent/ksync/interface_ksync.h @@ -94,6 +94,7 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { uint16_t tx_vlan_id_; uint32_t vrf_id_; bool persistent_; + PhysicalInterface::SubType subtype_; KSyncEntryPtr xconnect_; DISALLOW_COPY_AND_ASSIGN(InterfaceKSyncEntry); diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 99f8777b3b1..57ae1a22046 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -380,9 +380,11 @@ void PacketInterface::Delete(InterfaceTable *table, const std::string &ifname) { // Ethernet Interface routines ///////////////////////////////////////////////////////////////////////////// PhysicalInterface::PhysicalInterface(const std::string &name, VrfEntry *vrf, - bool persistent) : + SubType subtype) : Interface(Interface::PHYSICAL, nil_uuid(), name, vrf), - persistent_(persistent) { + persistent_(false), subtype_(subtype) { + if (subtype_ == VMWARE) + persistent_ = true; } PhysicalInterface::~PhysicalInterface() { @@ -401,18 +403,18 @@ DBEntryBase::KeyPtr PhysicalInterface::GetDBRequestKey() const { // Enqueue DBRequest to create a Host Interface void PhysicalInterface::CreateReq(InterfaceTable *table, const string &ifname, - const string &vrf_name, bool persistent) { + const string &vrf_name, SubType subtype) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, persistent)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); table->Enqueue(&req); } void PhysicalInterface::Create(InterfaceTable *table, const string &ifname, - const string &vrf_name, bool persistent) { + const string &vrf_name, SubType subtype) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, persistent)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); table->Process(req); } @@ -440,7 +442,7 @@ PhysicalInterfaceKey::~PhysicalInterfaceKey() { } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table) const { - return new PhysicalInterface(name_, NULL, false); + return new PhysicalInterface(name_, NULL, PhysicalInterface::INVALID); } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, @@ -454,7 +456,38 @@ Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, const PhysicalInterfaceData *phy_data = static_cast(data); - return new PhysicalInterface(name_, vrf, phy_data->persistent_); + return new PhysicalInterface(name_, vrf, phy_data->subtype_); +} + +void PhysicalInterface::PostAdd() { + InterfaceTable *table = static_cast(get_table()); + + if (subtype_ != VMWARE || table->agent()->test_mode()) { + return; + } + + int fd = socket(AF_LOCAL, SOCK_STREAM, 0); + assert(fd >= 0); + + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE); + if (ioctl(fd, SIOCGIFFLAGS, (void *)&ifr) < 0) { + LOG(ERROR, "Error <" << errno << ": " << strerror(errno) << + "> setting promiscuous flag for interface <" << name_ << ">"); + close(fd); + return; + } + + ifr.ifr_flags |= IFF_PROMISC; + if (ioctl(fd, SIOCSIFFLAGS, (void *)&ifr) < 0) { + LOG(ERROR, "Error <" << errno << ": " << strerror(errno) << + "> setting promiscuous flag for interface <" << name_ << ">"); + close(fd); + return; + } + + close(fd); } InterfaceKey *PhysicalInterfaceKey::Clone() const { @@ -462,8 +495,8 @@ InterfaceKey *PhysicalInterfaceKey::Clone() const { } PhysicalInterfaceData::PhysicalInterfaceData(const std::string &vrf_name, - bool persistent) - : InterfaceData(), persistent_(persistent) { + PhysicalInterface::SubType subtype) + : InterfaceData(), subtype_(subtype) { EthInit(vrf_name); } diff --git a/src/vnsw/agent/oper/physical_interface.h b/src/vnsw/agent/oper/physical_interface.h index 62604c5c164..4cda1b90877 100644 --- a/src/vnsw/agent/oper/physical_interface.h +++ b/src/vnsw/agent/oper/physical_interface.h @@ -11,14 +11,22 @@ ///////////////////////////////////////////////////////////////////////////// class PhysicalInterface : public Interface { public: - PhysicalInterface(const std::string &name, VrfEntry *vrf, - bool persistent); + enum SubType { + FABRIC, // Physical port connecting to fabric network + VMWARE, // For vmware, port connecting to contrail-vm-portgroup + INVALID + }; + + PhysicalInterface(const std::string &name, VrfEntry *vrf, SubType subtype); virtual ~PhysicalInterface(); bool CmpInterface(const DBEntry &rhs) const; std::string ToString() const { return "ETH <" + name() + ">"; } KeyPtr GetDBRequestKey() const; + void PostAdd(); + + SubType subtype() const { return subtype_; } // Lets kernel know if physical interface is to be kept after agent exits or // dies. If its true keep the interface, else remove it. // Currently only vnware physical interface is persistent. @@ -27,19 +35,21 @@ class PhysicalInterface : public Interface { // Helper functions static void CreateReq(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, bool persistent); + const std::string &vrf_name, SubType subtype); static void Create(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, bool persistent); + const std::string &vrf_name, SubType sub_type); static void DeleteReq(InterfaceTable *table, const std::string &ifname); static void Delete(InterfaceTable *table, const std::string &ifname); private: bool persistent_; + SubType subtype_; DISALLOW_COPY_AND_ASSIGN(PhysicalInterface); }; struct PhysicalInterfaceData : public InterfaceData { - PhysicalInterfaceData(const std::string &vrf_name, bool persistent); - bool persistent_; + PhysicalInterfaceData(const std::string &vrf_name, + PhysicalInterface::SubType subtype); + PhysicalInterface::SubType subtype_; }; struct PhysicalInterfaceKey : public InterfaceKey { diff --git a/src/vnsw/agent/oper/test/SConscript b/src/vnsw/agent/oper/test/SConscript index c8acee0f042..9524b31fbe1 100644 --- a/src/vnsw/agent/oper/test/SConscript +++ b/src/vnsw/agent/oper/test/SConscript @@ -60,7 +60,7 @@ instance_manager_test = env.UnitTest( 'instance_manager_test', ['instance_manager_test.cc']) env.Alias('agent:instance_manager_test', instance_manager_test) -oper_test_suite.append(instance_manager_test) +oper_flaky_test_suite.append(instance_manager_test) loadbalancer_test = env.UnitTest( 'loadbalancer_test', diff --git a/src/vnsw/agent/pkt/test/test_flowtable.cc b/src/vnsw/agent/pkt/test/test_flowtable.cc index 35e1f682eb4..58621ea78db 100644 --- a/src/vnsw/agent/pkt/test/test_flowtable.cc +++ b/src/vnsw/agent/pkt/test/test_flowtable.cc @@ -490,7 +490,7 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), FlowTableTest::eth_itf, Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); client->WaitForIdle(); } diff --git a/src/vnsw/agent/pkt/test/test_pkt.cc b/src/vnsw/agent/pkt/test/test_pkt.cc index c861dd1a722..8e105dce6e0 100644 --- a/src/vnsw/agent/pkt/test/test_pkt.cc +++ b/src/vnsw/agent/pkt/test/test_pkt.cc @@ -150,7 +150,7 @@ TEST_F(PktTest, FlowAdd_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "vnet0", Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); client->WaitForIdle(); TxMplsPacket(2, "1.1.1.2", "10.1.1.1", 0, "2.2.2.2", "3.3.3.3", 1); diff --git a/src/vnsw/agent/pkt/test/test_pkt_flow.cc b/src/vnsw/agent/pkt/test/test_pkt_flow.cc index e3698c48169..5782331dcaa 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_flow.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_flow.cc @@ -3647,7 +3647,7 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_itf, Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_fip_cfg.cc b/src/vnsw/agent/test/test_fip_cfg.cc index 1beac71a01a..ebd755ef4e4 100644 --- a/src/vnsw/agent/test/test_fip_cfg.cc +++ b/src/vnsw/agent/test/test_fip_cfg.cc @@ -187,7 +187,7 @@ TEST_F(CfgTest, FloatingIp_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "enet1", Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); client->WaitForIdle(); AddArp("10.1.1.2", "00:00:00:00:00:02", "enet1"); diff --git a/src/vnsw/agent/test/test_l2route.cc b/src/vnsw/agent/test/test_l2route.cc index 4fd528e6255..7ef3487aa61 100644 --- a/src/vnsw/agent/test/test_l2route.cc +++ b/src/vnsw/agent/test/test_l2route.cc @@ -83,7 +83,8 @@ class RouteTest : public ::testing::Test { VrfAddReq(vrf_name_.c_str()); PhysicalInterface::CreateReq(agent_->interface_table(), eth_name_, - agent_->fabric_vrf_name(), false); + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_mirror.cc b/src/vnsw/agent/test/test_mirror.cc index 6936ff295da..cda26b5c9e0 100644 --- a/src/vnsw/agent/test/test_mirror.cc +++ b/src/vnsw/agent/test/test_mirror.cc @@ -41,7 +41,8 @@ class MirrorTableTest : public ::testing::Test { client->Reset(); nh_count_ = agent_->nexthop_table()->Size(); PhysicalInterface::CreateReq(agent_->interface_table(), - eth_itf, agent_->fabric_vrf_name(), false); + eth_itf, agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC); fabric_gw_ip_ = Ip4Address::from_string("10.1.1.254"); uint16_t sport = 10000; unsigned long ip = 0x0a010102; diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index 577bc614138..524129a51bf 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -103,7 +103,7 @@ class RouteTest : public ::testing::Test { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_name_, Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); diff --git a/src/vnsw/agent/test/test_vmport_cfg.cc b/src/vnsw/agent/test/test_vmport_cfg.cc index fbb79e1d108..6fd078a6a3d 100644 --- a/src/vnsw/agent/test/test_vmport_cfg.cc +++ b/src/vnsw/agent/test/test_vmport_cfg.cc @@ -54,13 +54,16 @@ void DoInterfaceSandesh(std::string name) { } class CfgTest : public ::testing::Test { +public: virtual void SetUp() { + agent_ = Agent::GetInstance(); } virtual void TearDown() { EXPECT_EQ(0U, Agent::GetInstance()->acl_table()->Size()); } + Agent *agent_; }; TEST_F(CfgTest, AddDelVmPortNoVn_1) { @@ -1190,14 +1193,27 @@ TEST_F(CfgTest, Basic_1) { {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 5, 5}, }; + PhysicalInterfaceKey key(eth_intf); + PhysicalInterface *phy_intf = NULL; + client->Reset(); PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), - eth_intf, vrf_name, false); + eth_intf, vrf_name, PhysicalInterface::FABRIC); client->WaitForIdle(); + phy_intf = static_cast + (agent_->interface_table()->FindActiveEntry(&key)); + EXPECT_TRUE(phy_intf == NULL); + PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_intf, Agent::GetInstance()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC); client->WaitForIdle(); + + phy_intf = static_cast + (agent_->interface_table()->FindActiveEntry(&key)); + EXPECT_TRUE(phy_intf->persistent() == false); + EXPECT_TRUE(phy_intf->subtype() == PhysicalInterface::FABRIC); + InetInterface::CreateReq(Agent::GetInstance()->interface_table(), "vhost10", InetInterface::VHOST, Agent::GetInstance()->fabric_vrf_name(), From 3b44c7ca08c18837ea2cb23b026dbb300622f991 Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Sun, 2 Nov 2014 15:46:03 -0800 Subject: [PATCH 167/218] Minor cleanup of BgpRoute introspect code Following changes are implemented: - Split code to display extended community into a separate funciton - Make BgpRoute::FillRouteInfo const Change-Id: Ia14d341e0ed83a9f6be67cd15651dce03638789c --- src/bgp/bgp_route.cc | 122 +++++++++++++++++++++++-------------------- src/bgp/bgp_route.h | 4 +- 2 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/bgp/bgp_route.cc b/src/bgp/bgp_route.cc index 7054d40c449..5bf4cf81b9f 100644 --- a/src/bgp/bgp_route.cc +++ b/src/bgp/bgp_route.cc @@ -23,6 +23,8 @@ #include "bgp/security_group/security_group.h" #include "bgp/tunnel_encap/tunnel_encap.h" +using std::string; +using std::vector; BgpRoute::BgpRoute() { } @@ -232,9 +234,10 @@ size_t BgpRoute::count() const { return GetPathList().size(); } -void BgpRoute::FillRouteInfo(BgpTable *table, ShowRouteBrief *show_route) { +void BgpRoute::FillRouteInfo(const BgpTable *table, + ShowRouteBrief *show_route) const { show_route->set_prefix(ToString()); - std::vector show_route_paths; + vector show_route_paths; for (Route::PathList::const_iterator it = GetPathList().begin(); it != GetPathList().end(); ++it) { const BgpPath *path = static_cast(it.operator->()); @@ -265,14 +268,69 @@ void BgpRoute::FillRouteInfo(BgpTable *table, ShowRouteBrief *show_route) { show_route->set_paths(show_route_paths); } -void BgpRoute::FillRouteInfo(BgpTable *table, ShowRoute *show_route) { +static void FillRoutePathExtCommunityInfo(const BgpTable *table, + const ExtCommunity *extcomm, + ShowRoutePath *show_path) { const RoutingInstance *ri = table->routing_instance(); const RoutingInstanceMgr *ri_mgr = ri->manager(); + const ExtCommunity::ExtCommunityList &v = extcomm->communities(); + for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin(); + it != v.end(); ++it) { + if (ExtCommunity::is_route_target(*it)) { + RouteTarget rt(*it); + show_path->communities.push_back(rt.ToString()); + } else if (ExtCommunity::is_default_gateway(*it)) { + DefaultGateway dgw(*it); + show_path->communities.push_back(dgw.ToString()); + } else if (ExtCommunity::is_es_import(*it)) { + EsImport es_import(*it); + show_path->communities.push_back(es_import.ToString()); + } else if (ExtCommunity::is_esi_label(*it)) { + EsiLabel esi_label(*it); + show_path->communities.push_back(esi_label.ToString()); + } else if (ExtCommunity::is_mac_mobility(*it)) { + MacMobility mm(*it); + show_path->communities.push_back(mm.ToString()); + show_path->set_sequence_no(mm.ToString()); + } else if (ExtCommunity::is_origin_vn(*it)) { + OriginVn origin_vn(*it); + show_path->communities.push_back(origin_vn.ToString()); + int vn_index = origin_vn.vn_index(); + show_path->set_origin_vn( + ri_mgr->GetVirtualNetworkByVnIndex(vn_index)); + } else if (ExtCommunity::is_security_group(*it)) { + SecurityGroup sg(*it); + show_path->communities.push_back(sg.ToString()); + } else if (ExtCommunity::is_route_target(*it)) { + SiteOfOrigin soo(*it); + show_path->communities.push_back(soo.ToString()); + } else if (ExtCommunity::is_tunnel_encap(*it)) { + TunnelEncap encap(*it); + show_path->communities.push_back(encap.ToString()); + TunnelEncapType::Encap id = encap.tunnel_encap(); + show_path->tunnel_encap.push_back( + TunnelEncapType::TunnelEncapToString(id)); + } else { + char temp[50]; + int len = snprintf(temp, sizeof(temp), "ext community: "); + for (size_t i=0; i < it->size(); i++) { + len += snprintf(temp+len, sizeof(temp) - len, "%02x", (*it)[i]); + } + show_path->communities.push_back(string(temp)); + } + } +} + +void BgpRoute::FillRouteInfo(const BgpTable *table, + ShowRoute *show_route) const { + const RoutingInstance *ri = table->routing_instance(); + show_route->set_prefix(ToString()); - show_route->set_last_modified(integerToString(UTCUsecToPTime(last_change_at()))); + show_route->set_last_modified( + integerToString(UTCUsecToPTime(last_change_at()))); - std::vector show_route_paths; + vector show_route_paths; for(Route::PathList::const_iterator it = GetPathList().begin(); it != GetPathList().end(); it++) { const BgpPath *path = static_cast(it.operator->()); @@ -300,7 +358,8 @@ void BgpRoute::FillRouteInfo(BgpTable *table, ShowRoute *show_route) { srp.set_next_hop(attr->nexthop().to_string()); srp.set_label(path->GetLabel()); srp.set_flags(path->GetFlags()); - srp.set_last_modified(integerToString(UTCUsecToPTime(path->time_stamp_usecs()))); + srp.set_last_modified( + integerToString(UTCUsecToPTime(path->time_stamp_usecs()))); if (path->IsReplicated()) { const BgpSecondaryPath *replicated; replicated = static_cast(path); @@ -315,56 +374,7 @@ void BgpRoute::FillRouteInfo(BgpTable *table, ShowRoute *show_route) { srp.communities.push_back(comm.ToString()); } if (attr->ext_community()) { - ExtCommunitySpec ext_comm; - const ExtCommunity::ExtCommunityList &v = - attr->ext_community()->communities(); - for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin(); - it != v.end(); ++it) { - if (ExtCommunity::is_route_target(*it)) { - RouteTarget rt(*it); - srp.communities.push_back(rt.ToString()); - } else if (ExtCommunity::is_default_gateway(*it)) { - DefaultGateway dgw(*it); - srp.communities.push_back(dgw.ToString()); - } else if (ExtCommunity::is_es_import(*it)) { - EsImport es_import(*it); - srp.communities.push_back(es_import.ToString()); - } else if (ExtCommunity::is_esi_label(*it)) { - EsiLabel esi_label(*it); - srp.communities.push_back(esi_label.ToString()); - } else if (ExtCommunity::is_mac_mobility(*it)) { - MacMobility mm(*it); - srp.communities.push_back(mm.ToString()); - srp.set_sequence_no(mm.ToString()); - } else if (ExtCommunity::is_origin_vn(*it)) { - OriginVn origin_vn(*it); - srp.communities.push_back(origin_vn.ToString()); - int vn_index = origin_vn.vn_index(); - srp.set_origin_vn( - ri_mgr->GetVirtualNetworkByVnIndex(vn_index)); - } else if (ExtCommunity::is_security_group(*it)) { - SecurityGroup sg(*it); - srp.communities.push_back(sg.ToString()); - } else if (ExtCommunity::is_route_target(*it)) { - SiteOfOrigin soo(*it); - srp.communities.push_back(soo.ToString()); - } else if (ExtCommunity::is_tunnel_encap(*it)) { - TunnelEncap encap(*it); - srp.communities.push_back(encap.ToString()); - TunnelEncapType::Encap id = encap.tunnel_encap(); - srp.tunnel_encap.push_back( - TunnelEncapType::TunnelEncapToString(id)); - } else { - char temp[50]; - int len = snprintf(temp, sizeof(temp), "ext community: "); - - for (size_t i=0; i < it->size(); i++) { - len += snprintf(temp+len, sizeof(temp) - len, "%02x", - (*it)[i]); - } - srp.communities.push_back(std::string(temp)); - } - } + FillRoutePathExtCommunityInfo(table, attr->ext_community(), &srp); } if (!table->IsVpnTable() && path->IsVrfOriginated()) { srp.set_origin_vn(ri->GetVirtualNetworkName()); diff --git a/src/bgp/bgp_route.h b/src/bgp/bgp_route.h index 77c7e5be68b..913350bb20a 100644 --- a/src/bgp/bgp_route.h +++ b/src/bgp/bgp_route.h @@ -64,8 +64,8 @@ class BgpRoute : public Route { size_t count() const; // Fill info needed for introspect - void FillRouteInfo(BgpTable *table, ShowRouteBrief *show_route); - void FillRouteInfo(BgpTable *table, ShowRoute *show_route); + void FillRouteInfo(const BgpTable *table, ShowRouteBrief *show_route) const; + void FillRouteInfo(const BgpTable *table, ShowRoute *show_route) const; private: From f8b252d6a70835a742abad0a54b39cfa0257605e Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Mon, 3 Nov 2014 11:28:39 +0530 Subject: [PATCH 168/218] Build physical-device-vn table based on logical-interface config In current design, physical-device-vn table was built on link between physical-router and virtual-network. This link is not expected in case of OVS. For OVS, the table should be built from - - - - --- src/vnsw/agent/cfg/cfg_listener.cc | 26 ++++++ src/vnsw/agent/cfg/cfg_listener.h | 11 +++ .../agent/oper/ifmap_dependency_manager.cc | 4 +- src/vnsw/agent/oper/vm_interface.cc | 20 +++- src/vnsw/agent/oper/vm_interface.h | 4 +- .../physical_devices/ovs_tor_agent/SConscript | 2 + .../physical_devices/tables/device_manager.cc | 16 ++-- .../physical_devices/tables/logical_port.cc | 4 +- .../tables/physical_device.cc | 27 +++++- .../physical_devices/tables/physical_device.h | 12 ++- .../tables/physical_device_vn.cc | 92 +++++++++++-------- .../tables/physical_device_vn.h | 3 + .../test/physical-device-vn.xml | 63 ++++++++++--- src/vnsw/agent/test-xml/test_xml.cc | 3 + 14 files changed, 215 insertions(+), 72 deletions(-) diff --git a/src/vnsw/agent/cfg/cfg_listener.cc b/src/vnsw/agent/cfg/cfg_listener.cc index 11c588a8c3f..92aa12a47fa 100644 --- a/src/vnsw/agent/cfg/cfg_listener.cc +++ b/src/vnsw/agent/cfg/cfg_listener.cc @@ -416,3 +416,29 @@ IFMapNode *CfgListener::FindAdjacentIFMapNode(const Agent *agent, return NULL; } + +// Invoke callback for each adjacent node of given "type" +uint32_t CfgListener::ForEachAdjacentIFMapNode(const Agent *agent, + IFMapNode *node, + const char *type, + AgentKey *key, + AgentData *data, + IFMapNodeCb cb) { + uint32_t count = 0; + IFMapAgentTable *table = static_cast(node->table()); + for (DBGraphVertex::adjacency_iterator iter = + node->begin(table->GetGraph()); + iter != node->end(table->GetGraph()); ++iter) { + IFMapNode *adj_node = static_cast(iter.operator->()); + if (SkipNode(adj_node)) { + continue; + } + + if (strcmp(adj_node->table()->Typename(), type) == 0) { + count++; + (cb)(agent, type, adj_node, key, data); + } + } + + return count; +} diff --git a/src/vnsw/agent/cfg/cfg_listener.h b/src/vnsw/agent/cfg/cfg_listener.h index 99cd6ef79e9..a82d4afd4a5 100644 --- a/src/vnsw/agent/cfg/cfg_listener.h +++ b/src/vnsw/agent/cfg/cfg_listener.h @@ -64,6 +64,17 @@ class CfgListener { bool SkipNode(IFMapNode *node); bool SkipNode(IFMapNode *node, IFMapAgentTable *table); + // Callback invoked for each IFMap neighbor node + typedef boost::function + IFMapNodeCb; + // Iterate thru all IFMap neighbor nodes and invoke callback for each + // neighbor of given type + uint32_t ForEachAdjacentIFMapNode(const Agent *agent, IFMapNode *node, + const char *name, AgentKey *key, + AgentData *data, IFMapNodeCb cb); + IFMapNode *FindAdjacentIFMapNode(const Agent *agent, IFMapNode *node, const char *name); private: diff --git a/src/vnsw/agent/oper/ifmap_dependency_manager.cc b/src/vnsw/agent/oper/ifmap_dependency_manager.cc index 1c947def45c..659f41a674a 100644 --- a/src/vnsw/agent/oper/ifmap_dependency_manager.cc +++ b/src/vnsw/agent/oper/ifmap_dependency_manager.cc @@ -141,7 +141,9 @@ void IFMapDependencyManager::Initialize() { ("instance-ip-virtual-machine-interface", list_of("virtual-machine-interface-virtual-machine")) ("virtual-machine-interface-virtual-network", - list_of("virtual-machine-interface-virtual-machine")); + list_of("virtual-machine-interface-virtual-machine") + ("virtual-machine-interface-logical-interface") + ("logical-interface-virtual-machine-interface")); policy->insert(make_pair("virtual-machine-interface", react_vmi)); ReactionMap react_ip = map_list_of diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 4b0560b7a81..b01518a26dc 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,8 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), - sub_type_(VmInterface::NONE), subnet_(0), subnet_plen_(0) { + sub_type_(VmInterface::NONE), ifmap_node_(NULL), subnet_(0), + subnet_plen_(0) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -81,8 +83,8 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid, parent_(parent), local_preference_(VmInterface::INVALID), oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), - vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), subnet_(0), - subnet_plen_(0) { + vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), + ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -593,6 +595,7 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { } VmInterfaceConfigData *data = new VmInterfaceConfigData(); + data->ifmap_node_ = node; //Extract the local preference if (cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES)) { autogen::VirtualMachineInterfacePropertiesType prop = cfg->properties(); @@ -1113,6 +1116,8 @@ bool VmInterfaceConfigData::OnDelete(const InterfaceTable *table, vmi->ResetConfigurer(VmInterface::CONFIG); VmInterfaceConfigData data; vmi->Resync(table, &data); + if (ifmap_node_ != NULL) + table->operdb()->dependency_manager()->ResetObject(ifmap_node_); return true; } @@ -1316,6 +1321,15 @@ bool VmInterface::CopyConfig(const InterfaceTable *table, (table->agent()->interface_table()->FindActiveEntry(&key)); assert(parent_ != NULL); } + + if (ifmap_node_ != data->ifmap_node_) { + if (ifmap_node_ != NULL) + table->operdb()->dependency_manager()->ResetObject(ifmap_node_); + ifmap_node_ = data->ifmap_node_; + if (ifmap_node_) + table->operdb()->dependency_manager()->SetObject(ifmap_node_, this); + } + return ret; } diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index 3617b1339e1..529318f7c83 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -592,6 +592,7 @@ class VmInterface : public Interface { Ip6Address vm_ip6_gw_addr_; VmInterface::SubType sub_type_; uint8_t configurer_; + IFMapNode *ifmap_node_; Ip4Address subnet_; uint8_t subnet_plen_; DISALLOW_COPY_AND_ASSIGN(VmInterface); @@ -701,7 +702,7 @@ struct VmInterfaceConfigData : public VmInterfaceData { mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), sub_type_(VmInterface::NONE), - parent_(""), subnet_(0), subnet_plen_(0) { + parent_(""), ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { } virtual ~VmInterfaceConfigData() { } @@ -745,6 +746,7 @@ struct VmInterfaceConfigData : public VmInterfaceData { VmInterface::AllowedAddressPairList allowed_address_pair_list_; VmInterface::SubType sub_type_; std::string parent_; + IFMapNode *ifmap_node_; Ip4Address subnet_; uint8_t subnet_plen_; }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript index ca013219c5c..e934174ccd8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/SConscript @@ -26,6 +26,8 @@ env.Append(LIBS = [ 'physical_devices' ]) +env.Append(LIBS = ['ssl', 'crypto']) + env.GenerateBuildInfoCode( target='buildinfo.cc', source = ['main.cc'], diff --git a/src/vnsw/agent/physical_devices/tables/device_manager.cc b/src/vnsw/agent/physical_devices/tables/device_manager.cc index b296cb65845..2885efff140 100644 --- a/src/vnsw/agent/physical_devices/tables/device_manager.cc +++ b/src/vnsw/agent/physical_devices/tables/device_manager.cc @@ -62,18 +62,22 @@ void PhysicalDeviceManager::RegisterDBClients() { IFMapDependencyManager *mgr = agent_->oper_db()->dependency_manager(); ReactionMap device_react = map_list_of - ("virtual-network", list_of("self")) - ("self", list_of("self")); + ("self", list_of("self")) + ("physical-router-physical-interface", list_of("self")); mgr->RegisterReactionMap("physical-router", device_react); ReactionMap physical_port_react = map_list_of - ("physical-router", list_of("self")) - ("self", list_of("self")); + ("self", list_of("self") ("physical-router-physical-interface")) + ("physical-interface-logical-interface", + list_of("physical-router-physical-interface")); mgr->RegisterReactionMap("physical-interface", physical_port_react); ReactionMap logical_port_react = map_list_of - ("physical-interface", list_of("self")) - ("self", list_of("self")); + ("self", list_of("physical-interface-logical-interface")) + ("physical-interface-logical-interface", + list_of("physical-router-physical-interface")) + ("logical-interface-virtual-machine-interface", + list_of("physical-interface-logical-interface")); mgr->RegisterReactionMap("logical-interface", logical_port_react); device_table_->RegisterDBClients(mgr); diff --git a/src/vnsw/agent/physical_devices/tables/logical_port.cc b/src/vnsw/agent/physical_devices/tables/logical_port.cc index 92310e4f4e9..3f3d5624ae9 100644 --- a/src/vnsw/agent/physical_devices/tables/logical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/logical_port.cc @@ -240,9 +240,9 @@ static void SetLogicalPortSandeshData(const LogicalPortEntry *entry, } if (entry->vm_interface()) { - data->set_physical_port(entry->vm_interface()->name()); + data->set_vif(entry->vm_interface()->name()); } else { - data->set_physical_port("INVALID"); + data->set_vif("INVALID"); } entry->SetSandeshData(data); } diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.cc b/src/vnsw/agent/physical_devices/tables/physical_device.cc index a0b93c35a25..d2f8b0c209b 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -69,7 +70,8 @@ void PhysicalDeviceEntry::SetKey(const DBRequestKey *key) { uuid_ = k->uuid_; } -bool PhysicalDeviceEntry::Copy(const PhysicalDeviceData *data) { +bool PhysicalDeviceEntry::Copy(const PhysicalDeviceTable *table, + const PhysicalDeviceData *data) { bool ret = false; if (fq_name_ != data->fq_name_) { @@ -108,6 +110,14 @@ bool PhysicalDeviceEntry::Copy(const PhysicalDeviceData *data) { ret = true; } + if (ifmap_node_ != data->ifmap_node_) { + OperDB *oper = table->agent()->oper_db(); + oper->dependency_manager()->SetObject(data->ifmap_node_, this); + if (ifmap_node_) + oper->dependency_manager()->ResetObject(ifmap_node_); + ifmap_node_ = data->ifmap_node_; + } + return ret; } @@ -126,7 +136,7 @@ DBEntry *PhysicalDeviceTable::Add(const DBRequest *req) { PhysicalDeviceData *data = static_cast (req->data.get()); PhysicalDeviceEntry *dev = new PhysicalDeviceEntry(key->uuid_); - dev->Copy(data); + dev->Copy(this, data); dev->SendObjectLog(AgentLogEvent::ADD); return dev; } @@ -135,7 +145,7 @@ bool PhysicalDeviceTable::OnChange(DBEntry *entry, const DBRequest *req) { PhysicalDeviceEntry *dev = static_cast(entry); PhysicalDeviceData *data = static_cast (req->data.get()); - bool ret = dev->Copy(data); + bool ret = dev->Copy(this, data); dev->SendObjectLog(AgentLogEvent::CHANGE); return ret; } @@ -143,6 +153,8 @@ bool PhysicalDeviceTable::OnChange(DBEntry *entry, const DBRequest *req) { bool PhysicalDeviceTable::Delete(DBEntry *entry, const DBRequest *req) { PhysicalDeviceEntry *dev = static_cast(entry); dev->SendObjectLog(AgentLogEvent::DELETE); + if (dev->ifmap_node_) + agent()->oper_db()->dependency_manager()->ResetObject(dev->ifmap_node_); return true; } @@ -161,6 +173,11 @@ DBTableBase *PhysicalDeviceTable::CreateTable(DB *db, const std::string &name) { // Config handling ///////////////////////////////////////////////////////////////////////////// void PhysicalDeviceTable::ConfigEventHandler(DBEntry *entry) { + PhysicalDeviceEntry *dev = static_cast(entry); + DBRequest req; + if (IFNodeToReq(dev->ifmap_node_, req) == true) { + Enqueue(&req); + } } void PhysicalDeviceTable::RegisterDBClients(IFMapDependencyManager *dep) { @@ -178,7 +195,7 @@ static PhysicalDeviceKey *BuildKey(const autogen::PhysicalRouter *router) { return new PhysicalDeviceKey(u); } -static PhysicalDeviceData *BuildData(const IFMapNode *node, +static PhysicalDeviceData *BuildData(IFMapNode *node, const autogen::PhysicalRouter *router) { boost::system::error_code ec; IpAddress ip = IpAddress(); @@ -186,7 +203,7 @@ static PhysicalDeviceData *BuildData(const IFMapNode *node, ip = IpAddress::from_string(router->dataplane_ip(), ec); mip = IpAddress::from_string(router->management_ip(), ec); return new PhysicalDeviceData(node->name(), router->display_name(), - router->vendor_name(), ip, mip, "OVS"); + router->vendor_name(), ip, mip, "OVS", node); } bool PhysicalDeviceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { diff --git a/src/vnsw/agent/physical_devices/tables/physical_device.h b/src/vnsw/agent/physical_devices/tables/physical_device.h index 2d844d52926..ce160ecf5cb 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device.h +++ b/src/vnsw/agent/physical_devices/tables/physical_device.h @@ -22,9 +22,10 @@ struct PhysicalDeviceData : public AgentData { PhysicalDeviceData(const std::string &fq_name, const std::string &name, const std::string &vendor, const IpAddress &ip, const IpAddress &mgmt_ip, - const std::string &protocol) : + const std::string &protocol, IFMapNode *ifmap_node) : AgentData(), fq_name_(fq_name), name_(name), vendor_(vendor), ip_(ip), - management_ip_(mgmt_ip), protocol_(protocol) { } + management_ip_(mgmt_ip), protocol_(protocol), ifmap_node_(ifmap_node) { + } virtual ~PhysicalDeviceData() { } std::string fq_name_; @@ -33,6 +34,7 @@ struct PhysicalDeviceData : public AgentData { IpAddress ip_; IpAddress management_ip_; std::string protocol_; + IFMapNode *ifmap_node_; }; class PhysicalDeviceEntry : AgentRefCount, @@ -44,7 +46,8 @@ class PhysicalDeviceEntry : AgentRefCount, } ManagementProtocol; explicit PhysicalDeviceEntry(const boost::uuids::uuid &id) : - uuid_(id), name_(""), vendor_(""), ip_(), protocol_(INVALID) { } + uuid_(id), name_(""), vendor_(""), ip_(), protocol_(INVALID), + ifmap_node_(NULL) { } virtual ~PhysicalDeviceEntry() { } virtual bool IsLess(const DBEntry &rhs) const; @@ -55,7 +58,7 @@ class PhysicalDeviceEntry : AgentRefCount, return AgentRefCount::GetRefCount(); } - bool Copy(const PhysicalDeviceData *data); + bool Copy(const PhysicalDeviceTable *table, const PhysicalDeviceData *data); const boost::uuids::uuid &uuid() const { return uuid_; } const std::string &fq_name() const { return fq_name_; } const std::string &name() const { return name_; } @@ -76,6 +79,7 @@ class PhysicalDeviceEntry : AgentRefCount, IpAddress ip_; IpAddress management_ip_; ManagementProtocol protocol_; + IFMapNode *ifmap_node_; DISALLOW_COPY_AND_ASSIGN(PhysicalDeviceEntry); }; diff --git a/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc b/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc index 8f7918ef282..41b90361ead 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_device_vn.cc @@ -130,16 +130,60 @@ void PhysicalDeviceVnTable::RegisterDBClients(IFMapDependencyManager *dep) { // Config handling routines ////////////////////////////////////////////////////////////////////////////// /* - * There is no IFMapNode for PhysicalDeviceVnEntry. The entries are built from - * link between physical-router and virtual-network. + * There is no IFMapNode for PhysicalDeviceVnEntry. We act on physical-router + * notification to build the PhysicalDeviceVnTable. * - * We act on physical-router notification to build the PhysicalDeviceVnTable. - * From a physical-router run thru all the links to find the virtual-networks. + * From a physical-router run iterate thru the links given below, + * - - - + * - * - * We dont get notification of link deletion between physical-router and - * virtual-network. Instead, we build a config-tree and audit the tree based - * on version-number to identify deleted entries + * Since there is no node for physical-device-vn, we build a config-tree and + * audit the tree based on version-number to identify deleted entries */ +void PhysicalDeviceVnTable::IterateConfig(const Agent *agent, const char *type, + IFMapNode *node, AgentKey *key, + AgentData *data, + const boost::uuids::uuid &dev_uuid) { + CfgListener *cfg = agent->cfg_listener(); + if (strcmp(type, "physical-interface") == 0) { + cfg->ForEachAdjacentIFMapNode + (agent, node, "logical-interface", NULL, NULL, + boost::bind(&PhysicalDeviceVnTable::IterateConfig, this, _1, _2, + _3, _4, _5, dev_uuid)); + return; + } + + if (strcmp(type, "logical-interface") != 0) { + return; + } + + IFMapNode *adj_node = NULL; + adj_node = cfg->FindAdjacentIFMapNode(agent, node, + "virtual-machine-interface"); + if (adj_node == NULL) + return; + + adj_node = cfg->FindAdjacentIFMapNode(agent, adj_node, "virtual-network"); + if (adj_node == NULL) + return; + + autogen::VirtualNetwork *vn = static_cast + (adj_node->GetObject()); + assert(vn); + autogen::IdPermsType id_perms = vn->id_perms(); + boost::uuids::uuid vn_uuid; + CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, + vn_uuid); + + PhysicalDeviceVnKey vn_key(dev_uuid, vn_uuid); + config_tree_[vn_key] = config_version_; + DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); + req.key.reset(new PhysicalDeviceVnKey(dev_uuid, vn_uuid)); + req.data.reset(new PhysicalDeviceVnData()); + Enqueue(&req); + return; +} + void PhysicalDeviceVnTable::ConfigUpdate(IFMapNode *node) { config_version_++; @@ -151,37 +195,11 @@ void PhysicalDeviceVnTable::ConfigUpdate(IFMapNode *node) { CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, router_uuid); - // Go thru virtual-networks linked and add/update them in the config tree - IFMapAgentTable *table = static_cast(node->table()); if (!node->IsDeleted()) { - for (DBGraphVertex::adjacency_iterator iter = - node->begin(table->GetGraph()); - iter != node->end(table->GetGraph()); ++iter) { - IFMapNode *adj_node = static_cast(iter.operator->()); - if (agent()->cfg_listener()->SkipNode(adj_node)) { - continue; - } - - if (strcmp(adj_node->table()->Typename(), "virtual-network") != 0) { - continue; - } - autogen::VirtualNetwork *vn = static_cast - (adj_node->GetObject()); - assert(vn); - autogen::IdPermsType id_perms = vn->id_perms(); - boost::uuids::uuid vn_uuid; - CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, - vn_uuid); - - PhysicalDeviceVnKey key(router_uuid, vn_uuid); - if (config_tree_.find(key) == config_tree_.end()) { - DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); - req.key.reset(new PhysicalDeviceVnKey(router_uuid, vn_uuid)); - req.data.reset(new PhysicalDeviceVnData()); - Enqueue(&req); - } - config_tree_[key] = config_version_; - } + agent()->cfg_listener()->ForEachAdjacentIFMapNode + (agent(), node, "physical-interface", NULL, NULL, + boost::bind(&PhysicalDeviceVnTable::IterateConfig, this, _1, _2, + _3, _4, _5, router_uuid)); } // Audit and delete entries with old version-number in config-tree diff --git a/src/vnsw/agent/physical_devices/tables/physical_device_vn.h b/src/vnsw/agent/physical_devices/tables/physical_device_vn.h index 74961ee65ea..9abe819b0ba 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_device_vn.h +++ b/src/vnsw/agent/physical_devices/tables/physical_device_vn.h @@ -98,6 +98,9 @@ class PhysicalDeviceVnTable : public AgentDBTable { virtual bool Delete(DBEntry *entry, const DBRequest *req); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + void IterateConfig(const Agent *agent, const char *type, IFMapNode *node, + AgentKey *key, AgentData *data, + const boost::uuids::uuid &dev_uuid); PhysicalDeviceTable *physical_device_table() const { return physical_device_table_; } diff --git a/src/vnsw/agent/physical_devices/test/physical-device-vn.xml b/src/vnsw/agent/physical_devices/test/physical-device-vn.xml index 260f51864c8..c06022b5209 100644 --- a/src/vnsw/agent/physical_devices/test/physical-device-vn.xml +++ b/src/vnsw/agent/physical_devices/test/physical-device-vn.xml @@ -1,31 +1,68 @@ - - + + + + + + - + right="physical-interface" right-name="intf-1"/> + present="no" /> - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + diff --git a/src/vnsw/agent/test-xml/test_xml.cc b/src/vnsw/agent/test-xml/test_xml.cc index 39327c36963..61f7a7696c6 100644 --- a/src/vnsw/agent/test-xml/test_xml.cc +++ b/src/vnsw/agent/test-xml/test_xml.cc @@ -86,6 +86,9 @@ void LinkXmlNode(xml_node *parent, const string <ype, const string lname, n2 = n1.append_child("name"); n2.append_child(pugi::node_pcdata).set_value(rname.c_str()); + string mdata = ltype + "-" + rtype; + xml_node n3 = n.append_child("metadata"); + n3.append_attribute("type") = mdata.c_str(); return; } From 219d68701588f7c068dbac844bb26311c6556ad3 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Mon, 3 Nov 2014 14:19:48 +0530 Subject: [PATCH 169/218] Fixes stale nexthop issue. If none of the relevant composite NH is present and no multicast peer is created, ignore the request for L2 comp NH creation. Also fixes test_util to send dns_server address in IPAM. In tests currently its same as gateway IP specified in IPAM structure(under test). --- src/vnsw/agent/oper/agent_route.cc | 6 +++--- src/vnsw/agent/test/test_util.cc | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index eba83b59227..09a645c01fb 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -761,9 +761,9 @@ bool AgentRoute::ReComputeMulticastPaths(AgentPath *path, bool del) { if ((local_peer_path == NULL) && (tor_peer_path == NULL) && (evpn_peer_path == NULL) && - (fabric_peer_path == NULL) && - (multicast_peer_path != NULL)) { - RemovePath(multicast_peer_path); + (fabric_peer_path == NULL)) { + if (multicast_peer_path != NULL) + RemovePath(multicast_peer_path); return true; } diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 85e1cc32259..516846b00cc 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -180,6 +180,7 @@ void AddNodeString(char *buff, int &len, const char *nodename, const char *name, str << " " << ipam[i].plen << "\n"; str << " \n"; str << " " << ipam[i].gw << "\n"; + str << " " << ipam[i].gw << "\n"; str << " " << dhcp_enable << "\n"; if (add_subnet_tags) str << add_subnet_tags << "\n"; From ff073b5bd8d8151c13e50bdb07e10f67d5ec500c Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Mon, 3 Nov 2014 14:47:06 +0530 Subject: [PATCH 170/218] Fix memory leak in physical-device-vn UT --- src/vnsw/agent/physical_devices/test/physical-device-vn.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vnsw/agent/physical_devices/test/physical-device-vn.xml b/src/vnsw/agent/physical_devices/test/physical-device-vn.xml index c06022b5209..cb41baae097 100644 --- a/src/vnsw/agent/physical_devices/test/physical-device-vn.xml +++ b/src/vnsw/agent/physical_devices/test/physical-device-vn.xml @@ -47,6 +47,8 @@ + Date: Mon, 3 Nov 2014 01:52:25 -0800 Subject: [PATCH 171/218] remove the earlier change done in neutron plugin for allocating dns service address --- .../vnc_openstack/neutron_plugin_db.py | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 5e7e20ef198..e3ed2c24813 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -2369,20 +2369,6 @@ def subnet_create(self, subnet_q): net_obj._pending_field_updates.add('network_ipam_refs') self._virtual_network_update(net_obj) - # allocate an IP address from the subnet for - # service address (dns_server_address) - try: - subnet = subnet_q['cidr'] - service_node_address = \ - self._vnc_lib.virtual_network_ip_alloc(vnobj=net_obj, count=1, - subnet=subnet) - subnet_vnc.set_dns_server_address(service_node_address[0]) - net_obj._pending_field_updates.add('network_ipam_refs') - self._virtual_network_update(net_obj) - except Exception as e: - self._raise_contrail_exception('BadRequest', resource='subnet', - msg='Unable to create internal service address in the subnet') - # allocate an id to the subnet and store mapping with # api-server subnet_id = subnet_vnc.subnet_uuid @@ -2514,14 +2500,6 @@ def subnet_delete(self, subnet_id): net_id) != subnet_key] if len(orig_subnets) != len(new_subnets): # matched subnet to be deleted - - # Free the IP allocated during subnet create (this IP was - # (used as service node address -> dns_server_address) - deleted_subnets = list(set(orig_subnets) - set(new_subnets)) - for subnet_vnc in deleted_subnets: - self._vnc_lib.virtual_network_ip_free(vnobj=net_obj, - ip_list=[subnet_vnc.dns_server_address]) - ipam_ref['attr'].set_ipam_subnets(new_subnets) net_obj._pending_field_updates.add('network_ipam_refs') try: From bab912d62ec6f25f05df1ded69a735aee81fad74 Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Mon, 3 Nov 2014 15:00:57 -0800 Subject: [PATCH 172/218] Fix couple of corner cases in bgp_xmpp_test - Wait for membership manager to process all events - Use correct message count in ShowXmppServer test Change-Id: Ie5153f7feffaa10bf35c50eb11acabaaeb84ba0b --- src/bgp/bgp_xmpp_channel.cc | 6 ++++++ src/bgp/test/bgp_xmpp_test.cc | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/bgp/bgp_xmpp_channel.cc b/src/bgp/bgp_xmpp_channel.cc index 48a86a2f4c1..fd38ff65713 100644 --- a/src/bgp/bgp_xmpp_channel.cc +++ b/src/bgp/bgp_xmpp_channel.cc @@ -1681,6 +1681,9 @@ bool BgpXmppChannel::ResumeClose() { void BgpXmppChannel::RegisterTable(BgpTable *table, int instance_id) { PeerRibMembershipManager *mgr = bgp_server_->membership_mgr(); + BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG, + BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA, + "Register to table " << table->name()); mgr->Register(peer_.get(), table, bgp_policy_, instance_id, boost::bind(&BgpXmppChannel::MembershipRequestCallback, this, _1, _2)); @@ -1688,6 +1691,9 @@ void BgpXmppChannel::RegisterTable(BgpTable *table, int instance_id) { void BgpXmppChannel::UnregisterTable(BgpTable *table) { PeerRibMembershipManager *mgr = bgp_server_->membership_mgr(); + BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG, + BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA, + "Unregister to table " << table->name()); mgr->Unregister(peer_.get(), table, boost::bind(&BgpXmppChannel::MembershipRequestCallback, this, _1, _2)); diff --git a/src/bgp/test/bgp_xmpp_test.cc b/src/bgp/test/bgp_xmpp_test.cc index 8f65251eb78..72c0bf0312d 100644 --- a/src/bgp/test/bgp_xmpp_test.cc +++ b/src/bgp/test/bgp_xmpp_test.cc @@ -9,6 +9,7 @@ #include "base/test/task_test_util.h" #include "bgp/bgp_config_parser.h" #include "bgp/bgp_factory.h" +#include "bgp/bgp_peer_membership.h" #include "bgp/bgp_sandesh.h" #include "bgp/bgp_session_manager.h" #include "bgp/bgp_xmpp_channel.h" @@ -524,6 +525,11 @@ TEST_F(BgpXmppUnitTest, Connection) { WAIT_EQ(8, bgp_channel_manager_->channel_->Count()); BGP_DEBUG_UT("Received unsubscribe message 3 at Server \n "); + // Wait for all unsubscribe requests to get processed + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(a_->membership_mgr()->IsQueueEmpty()); + TASK_UTIL_EXPECT_TRUE(b_->membership_mgr()->IsQueueEmpty()); + // show route cout << "ValidateShowRouteResponse for empty tables:" << endl; result.resize(0); @@ -584,7 +590,7 @@ TEST_F(BgpXmppUnitTest, ShowXmppServer) { memcpy(buf, data.data(), data.size()); xmpp_cchannel_->Peer()->SendUpdate(buf, data.size()); BGP_DEBUG_UT("Sent bytes: " << data.size()); - WAIT_EQ(1, bgp_channel_manager_->channel_->Count()); + WAIT_EQ(2, bgp_channel_manager_->channel_->Count()); BGP_DEBUG_UT("Received unsubscribe message 1 at Server"); BgpSandeshContext sandesh_context; From 706be2600ba1f18d0d03b54523b651ef8ac56f84 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 4 Nov 2014 02:45:51 -0800 Subject: [PATCH 173/218] Handle NULL ptr expection. --- .../ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index f81353aa71c..df9d9f4f772 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -29,7 +29,9 @@ UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, struct ovsdb_idl_row *row) : OvsdbEntry(table), mac_(ovsdb_wrapper_ucast_mac_local_mac(row)), logical_switch_name_(ovsdb_wrapper_ucast_mac_local_logical_switch(row)), - dest_ip_(ovsdb_wrapper_ucast_mac_local_dst_ip(row)) { + dest_ip_() { + if (ovsdb_wrapper_ucast_mac_local_dst_ip(row)) + dest_ip_ = ovsdb_wrapper_ucast_mac_local_dst_ip(row); } UnicastMacLocalEntry::~UnicastMacLocalEntry() { From 2e73e5dc47e96835d4715ff78b4b5130a2d48ffe Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 4 Nov 2014 08:58:36 -0800 Subject: [PATCH 174/218] fix logical_switch_table sync api to update all fields before returning. fix the key formation in logicalswitch ovsdbnotify Adding NULL check to retreive tunnel keys from ovsdb_wrapper api. --- .../ovsdb_client/logical_switch_ovsdb.cc | 14 +++++--------- .../ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c | 5 ++++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index ee5f8bac605..5b7e633c0fd 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -111,15 +111,16 @@ void LogicalSwitchEntry::OvsdbChange() { bool LogicalSwitchEntry::Sync(DBEntry *db_entry) { PhysicalDeviceVnEntry *entry = static_cast(db_entry); + bool change = false; if (vxlan_id_ != entry->vn()->GetVxLanId()) { vxlan_id_ = entry->vn()->GetVxLanId(); - return true; + change = true; } if (device_name_ != entry->device()->name()) { device_name_ = entry->device()->name(); - return true; + change = true; } - return false; + return change; } bool LogicalSwitchEntry::IsLess(const KSyncEntry &entry) const { @@ -183,17 +184,12 @@ LogicalSwitchTable::~LogicalSwitchTable() { void LogicalSwitchTable::OvsdbNotify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { - const char *name = ovsdb_wrapper_logical_switch_name(row); - int64_t vxlan = ovsdb_wrapper_logical_switch_tunnel_key(row); + LogicalSwitchEntry key(this, row); if (op == OvsdbClientIdl::OVSDB_DEL) { - LogicalSwitchEntry key(this, name); NotifyDeleteOvsdb((OvsdbDBEntry*)&key); - key.vxlan_id_ = vxlan; key.SendTrace(LogicalSwitchEntry::DEL_ACK); } else if (op == OvsdbClientIdl::OVSDB_ADD) { - LogicalSwitchEntry key(this, name); NotifyAddOvsdb((OvsdbDBEntry*)&key, row); - key.vxlan_id_ = vxlan; key.SendTrace(LogicalSwitchEntry::ADD_ACK); } else { assert(0); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index 175d016bfb3..48f8ca245f5 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -209,7 +209,10 @@ ovsdb_wrapper_logical_switch_tunnel_key(struct ovsdb_idl_row *row) { struct vteprec_logical_switch *ls = row ? CONTAINER_OF(row, struct vteprec_logical_switch, header_) : NULL; - return *ls->tunnel_key; + if (ls->n_tunnel_key == 0) { + return 0; + } + return ls->tunnel_key[0]; } struct ovsdb_idl_row * From db979b62891bf6ee40332d27e6de9353c4b3a37d Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 4 Nov 2014 22:23:49 -0800 Subject: [PATCH 175/218] Fixing renew of ksync db entry with a new oper db entry. Adding Test case for the same. --- src/ksync/ksync_object.cc | 12 ++++- src/ksync/test/ksync_db_test.cc | 84 ++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index effadcb7181..0617b9faeb1 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -232,7 +232,17 @@ void KSyncDBObject::Notify(DBTablePartBase *partition, DBEntryBase *e) { } delete key; entry->SetState(table, id_, ksync); - assert(ksync->GetDBEntry() == NULL); + DBEntry *old_db_entry = ksync->GetDBEntry(); + if (old_db_entry != NULL) { + // cleanup previous state id the old db entry is delete marked. + if (old_db_entry->IsDeleted()) { + CleanupOnDel(ksync); + } else { + // something wrong! two db entry in oper db points to same + // KSync entry. + assert(false); + } + } ksync->SetDBEntry(entry); need_sync = true; } diff --git a/src/ksync/test/ksync_db_test.cc b/src/ksync/test/ksync_db_test.cc index 8a91fdbbee1..3411e48ce1b 100644 --- a/src/ksync/test/ksync_db_test.cc +++ b/src/ksync/test/ksync_db_test.cc @@ -40,32 +40,37 @@ class TestUT : public ::testing::Test { class Vlan : public DBEntry { public: struct VlanKey : public DBRequestKey { - VlanKey(uint16_t tag) : DBRequestKey(), tag_(tag) { }; + VlanKey(string name, uint16_t tag) : DBRequestKey(), name_(name), + tag_(tag) { }; virtual ~VlanKey() { }; + string name_; uint16_t tag_; }; - Vlan(uint16_t tag) : DBEntry(), tag_(tag) { }; + Vlan(string name, uint16_t tag) : DBEntry(), name_(name), tag_(tag) { }; virtual ~Vlan() { }; bool IsLess(const DBEntry &rhs) const { const Vlan &vlan = static_cast(rhs); - return tag_ < vlan.tag_; + return name_ < vlan.name_; }; virtual string ToString() const { return "Vlan"; }; virtual void SetKey(const DBRequestKey *k) { const VlanKey *key = static_cast(k); + name_ = key->name_; tag_ = key->tag_; }; virtual KeyPtr GetDBRequestKey() const { - VlanKey *key = new VlanKey(tag_); + VlanKey *key = new VlanKey(name_, tag_); return DBEntryBase::KeyPtr(key); }; uint16_t GetTag() const {return tag_;}; + string name() const {return name_;} private: + string name_; uint16_t tag_; friend class VlanTable; DISALLOW_COPY_AND_ASSIGN(Vlan); @@ -78,13 +83,13 @@ class VlanTable : public DBTable { virtual std::auto_ptr AllocEntry(const DBRequestKey *k) const { const Vlan::VlanKey *key = static_cast(k); - Vlan *vlan = new Vlan(key->tag_); + Vlan *vlan = new Vlan(key->name_, key->tag_); return std::auto_ptr(static_cast(vlan)); } virtual DBEntry *Add(const DBRequest *req) { Vlan::VlanKey *key = static_cast(req->key.get()); - Vlan *vlan = new Vlan(key->tag_); + Vlan *vlan = new Vlan(key->name_, key->tag_); return vlan; } @@ -251,7 +256,7 @@ KSyncDBObject *VlanKSyncEntry::GetObject() { TEST_F(DBKSyncTest, Basic) { DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); @@ -263,7 +268,7 @@ TEST_F(DBKSyncTest, Basic) { EXPECT_EQ(VlanKSyncEntry::GetDelCount(), 0); req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); @@ -278,12 +283,12 @@ TEST_F(DBKSyncTest, Basic) { TEST_F(DBKSyncTest, AddDelCompress) { DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); @@ -299,7 +304,7 @@ TEST_F(DBKSyncTest, AddDelCompress) { TEST_F(DBKSyncTest, DuplicateDelete) { DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); @@ -311,13 +316,13 @@ TEST_F(DBKSyncTest, DuplicateDelete) { ksync_vlan = VlanKSyncObject::GetKSyncObject()->Find(&v); req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); task_util::WaitForIdle(); req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); task_util::WaitForIdle(); @@ -334,7 +339,7 @@ TEST_F(DBKSyncTest, DuplicateDelete) { TEST_F(DBKSyncTest, Del_Ack_Wait_to_Temp) { DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); @@ -349,7 +354,7 @@ TEST_F(DBKSyncTest, Del_Ack_Wait_to_Temp) { k_vlan->set_no_ack_trigger(false); ksync_vlan = NULL; req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); task_util::WaitForIdle(); @@ -363,14 +368,14 @@ TEST_F(DBKSyncTest, Del_Ack_Wait_to_Temp) { k_vlan->set_no_ack_trigger(true); req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); task_util::WaitForIdle(); EXPECT_EQ(ksync_vlan->GetState(), KSyncEntry::IN_SYNC); req.oper = DBRequest::DB_ENTRY_DELETE; - req.key.reset(new Vlan::VlanKey(10)); + req.key.reset(new Vlan::VlanKey("vlan10", 10)); req.data.reset(NULL); itbl->Enqueue(&req); task_util::WaitForIdle(); @@ -384,6 +389,51 @@ TEST_F(DBKSyncTest, Del_Ack_Wait_to_Temp) { EXPECT_EQ(VlanKSyncEntry::GetDelCount(), 2); } +TEST_F(DBKSyncTest, KSyncEntryRenewWithNewDBEntry) { + DBRequest req; + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + req.key.reset(new Vlan::VlanKey("vlan10", 10)); + req.data.reset(NULL); + itbl->Enqueue(&req); + + //Get a reference to vlan entry, to avoid deletion + task_util::WaitForIdle(); + VlanKSyncEntry v(10); + KSyncEntry::KSyncEntryPtr ksync_vlan; + ksync_vlan = VlanKSyncObject::GetKSyncObject()->Find(&v); + + req.oper = DBRequest::DB_ENTRY_DELETE; + req.key.reset(new Vlan::VlanKey("vlan10", 10)); + req.data.reset(NULL); + itbl->Enqueue(&req); + task_util::WaitForIdle(); + + // Delete pending due to reference + EXPECT_EQ(ksync_vlan->GetState(), KSyncEntry::DEL_DEFER_REF); + + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + req.key.reset(new Vlan::VlanKey("new_vlan10", 10)); + req.data.reset(NULL); + itbl->Enqueue(&req); + task_util::WaitForIdle(); + + // Ksync should move to in sync and new db entry. + EXPECT_EQ(ksync_vlan->GetState(), KSyncEntry::IN_SYNC); + ksync_vlan = NULL; + + req.oper = DBRequest::DB_ENTRY_DELETE; + req.key.reset(new Vlan::VlanKey("new_vlan10", 10)); + req.data.reset(NULL); + itbl->Enqueue(&req); + task_util::WaitForIdle(); + + EXPECT_EQ(adc_notification, 2); + EXPECT_EQ(del_notification, 2); + + EXPECT_EQ(VlanKSyncEntry::GetAddCount(), 1); + EXPECT_EQ(VlanKSyncEntry::GetDelCount(), 1); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); LoggingInit(); From fbe04b4478cdbd95a24d3399d1deaad8d6b6c42c Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 4 Nov 2014 23:22:41 -0800 Subject: [PATCH 176/218] fixing agent.gdb macro to use common definition --- src/vnsw/agent/test/agent.gdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vnsw/agent/test/agent.gdb b/src/vnsw/agent/test/agent.gdb index f20ade6a473..fe8b25c71f3 100644 --- a/src/vnsw/agent/test/agent.gdb +++ b/src/vnsw/agent/test/agent.gdb @@ -269,7 +269,7 @@ define pksync_entries help pksync_entries else # set the node equal to first node and end marker - set $Xtree = &((RouteKSyncObject *)$arg0)->tree_.tree_ + set $Xtree = &((KSyncDBObject *)$arg0)->tree_.tree_ set $Xnode = $Xtree->data_.node_plus_pred_.header_plus_size_.header_.left_ set $Xend = &($Xtree->data_.node_plus_pred_.header_plus_size_.header_) From 9f9fd28ff34d6c82a7660538b587310f78ddb775 Mon Sep 17 00:00:00 2001 From: Ashok Singh Date: Wed, 29 Oct 2014 10:15:57 -0700 Subject: [PATCH 177/218] Initial VCPE changes --- src/vnsw/agent/oper/vm_interface.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index b01518a26dc..bbdeef66db4 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -1858,12 +1858,14 @@ Ip4Address VmInterface::GetGateway() const { if (vn_.get() == NULL) { return ip; } + const VnIpam *ipam = NULL; if (subnet_.is_unspecified()) { ipam = vn_->GetIpam(ip_addr_); } else { ipam = vn_->GetIpam(subnet_); } + if (ipam) { ip = ipam->default_gw.to_v4(); } From ddacd2a7c66decb2fc22ac69947a1139f540d93a Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Thu, 6 Nov 2014 00:31:48 +0530 Subject: [PATCH 178/218] Enhancements to support tunnel/tap interface as physical ports Agent modifications to - support no-arp on physical/vhost interface. Agent reads the IFFLAGS from interface to find no-arp flag When interface is marked with no-arp, agent will send packets with pre-determined ethernet header - raw-ip on physical interface. Allow agent to send/receive raw-ip packets without ethernet header on physical-port. This is used when physical-interface is of type TUN --- src/vnsw/agent/init/agent_param.cc | 41 ++++++-- src/vnsw/agent/init/agent_param.h | 4 + src/vnsw/agent/init/contrail_init_common.cc | 16 ++- src/vnsw/agent/ksync/interface_ksync.cc | 39 +++++++- src/vnsw/agent/ksync/interface_ksync.h | 4 + src/vnsw/agent/ksync/nexthop_ksync.cc | 31 +++--- src/vnsw/agent/ksync/vnswif_listener_base.cc | 3 +- src/vnsw/agent/oper/agent_path.h | 19 ++++ src/vnsw/agent/oper/inet_interface.cc | 98 +++++++++++++------ src/vnsw/agent/oper/inet_unicast_route.cc | 45 +++++++++ src/vnsw/agent/oper/inet_unicast_route.h | 5 + src/vnsw/agent/oper/interface.cc | 37 ++++--- src/vnsw/agent/oper/nexthop.cc | 18 ++++ src/vnsw/agent/oper/nexthop.h | 3 + src/vnsw/agent/oper/physical_interface.h | 26 ++++- .../agent/oper/test/test_inet_interface.cc | 81 +++++++++++++++ src/vnsw/agent/oper/vm_interface.cc | 3 +- .../physical_devices/tables/physical_port.cc | 3 +- src/vnsw/agent/pkt/test/test_flowtable.cc | 3 +- src/vnsw/agent/pkt/test/test_pkt.cc | 3 +- src/vnsw/agent/pkt/test/test_pkt_flow.cc | 3 +- src/vnsw/agent/test/test_fip_cfg.cc | 3 +- src/vnsw/agent/test/test_l2route.cc | 3 +- src/vnsw/agent/test/test_mirror.cc | 3 +- src/vnsw/agent/test/test_route.cc | 3 +- src/vnsw/agent/test/test_vmport_cfg.cc | 6 +- 26 files changed, 423 insertions(+), 80 deletions(-) diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index fffc7446957..e14d349d0e7 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -735,7 +736,11 @@ void AgentParam::ComputeFlowLimits() { } } -static bool ValidateInterface(bool test_mode, const std::string &ifname) { +static bool ValidateInterface(bool test_mode, const std::string &ifname, + bool *no_arp, string *eth_encap) { + *no_arp = false; + *eth_encap = ""; + if (test_mode) { return true; } @@ -745,7 +750,7 @@ static bool ValidateInterface(bool test_mode, const std::string &ifname) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE); - int err = ioctl(fd, SIOCGIFHWADDR, (void *)&ifr); + int err = ioctl(fd, SIOCGIFFLAGS, (void *)&ifr); close (fd); if (err < 0) { @@ -754,6 +759,22 @@ static bool ValidateInterface(bool test_mode, const std::string &ifname) { return false; } + if ((ifr.ifr_flags & IFF_NOARP)) { + *no_arp = true; + } + + char fname[128]; + snprintf(fname, 128, "/sys/class/net/%s/type", ifname.c_str()); + FILE *f = fopen(fname, "r"); + if (f) { + int type; + if (fscanf(f, "%d", &type) >= 0) { + if (type == ARPHRD_NONE) { + *eth_encap = "none"; + } + } + } + return true; } @@ -764,8 +785,10 @@ int AgentParam::Validate() { return (EINVAL); } + bool no_arp; + string encap; // Check if interface is already present - if (ValidateInterface(test_mode_, vhost_.name_) == false) { + if (ValidateInterface(test_mode_, vhost_.name_, &no_arp, &encap) == false) { return (ENODEV); } @@ -776,7 +799,8 @@ int AgentParam::Validate() { } // Check if interface is already present - if (ValidateInterface(test_mode_, eth_port_) == false) { + if (ValidateInterface(test_mode_, eth_port_, ð_port_no_arp_, + ð_port_encap_type_) == false) { return (ENODEV); } @@ -788,7 +812,8 @@ int AgentParam::Validate() { return (EINVAL); } - if (ValidateInterface(test_mode_, vmware_physical_port_) == false) { + if (ValidateInterface(test_mode_, vmware_physical_port_, &no_arp, + &encap) == false) { return (ENODEV); } } @@ -824,6 +849,10 @@ void AgentParam::LogConfig() const { << "/" << vhost_.plen_); LOG(DEBUG, "vhost gateway : " << vhost_.gw_.to_string()); LOG(DEBUG, "Ethernet port : " << eth_port_); + LOG(DEBUG, "Ethernet Encap Type : " << eth_port_encap_type_); + if (eth_port_no_arp_) { + LOG(DEBUG, "Ethernet No-ARP : " << "TRUE"); + } LOG(DEBUG, "XMPP Server-1 : " << xmpp_server_1_); LOG(DEBUG, "XMPP Server-2 : " << xmpp_server_2_); LOG(DEBUG, "DNS Server-1 : " << dns_server_1_); @@ -898,7 +927,7 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, enable_hypervisor_options_(enable_hypervisor_options), enable_service_options_(enable_service_options), enable_tsn_(enable_tsn), tsn_ip_1_(), tsn_ip_2_(), - vhost_(), eth_port_(), + vhost_(), eth_port_(), eth_port_no_arp_(false), eth_port_encap_type_(), xmpp_instance_count_(), xmpp_server_1_(), xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dns_port_1_(ContrailPorts::DnsServerPort()), diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index 3573c173451..ee94f8dfccf 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -77,6 +77,8 @@ class AgentParam { const std::string &agent_name() const { return agent_name_; } const std::string ð_port() const { return eth_port_; } + const bool ð_port_no_arp() const { return eth_port_no_arp_; } + const std::string ð_port_encap_type() const { return eth_port_encap_type_; } const Ip4Address &tsn_ip_1() const { return tsn_ip_1_; } const Ip4Address &tsn_ip_2() const { return tsn_ip_2_; } const Ip4Address &xmpp_server_1() const { return xmpp_server_1_; } @@ -248,6 +250,8 @@ class AgentParam { PortInfo vhost_; std::string agent_name_; std::string eth_port_; + bool eth_port_no_arp_; + std::string eth_port_encap_type_; uint16_t xmpp_instance_count_; Ip4Address xmpp_server_1_; Ip4Address xmpp_server_2_; diff --git a/src/vnsw/agent/init/contrail_init_common.cc b/src/vnsw/agent/init/contrail_init_common.cc index 612f535a150..4ceaab3f815 100644 --- a/src/vnsw/agent/init/contrail_init_common.cc +++ b/src/vnsw/agent/init/contrail_init_common.cc @@ -117,12 +117,23 @@ void ContrailInitCommon::CreateVrf() { } } +static PhysicalInterface::EncapType ComputeEncapType(const string &encap) { + if (encap == "none") { + return PhysicalInterface::RAW_IP; + } + return PhysicalInterface::ETHERNET; +} + void ContrailInitCommon::CreateInterfaces() { InterfaceTable *table = agent()->interface_table(); + PhysicalInterface::EncapType type; + type = ComputeEncapType(agent_param()->eth_port_encap_type()); PhysicalInterface::Create(table, agent_param()->eth_port(), agent()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, type, + agent_param()->eth_port_no_arp()); + InetInterface::Create(table, agent_param()->vhost_name(), InetInterface::VHOST, agent()->fabric_vrf_name(), agent_param()->vhost_addr(), @@ -135,7 +146,8 @@ void ContrailInitCommon::CreateInterfaces() { PhysicalInterface::Create(agent()->interface_table(), agent_param()->vmware_physical_port(), agent()->fabric_vrf_name(), - PhysicalInterface::VMWARE); + PhysicalInterface::VMWARE, + PhysicalInterface::ETHERNET, false); } InetInterfaceKey key(agent()->vhost_interface_name()); diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 1b677dd3488..40d129e922b 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -65,7 +65,9 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, vrf_id_(entry->vrf_id_), persistent_(entry->persistent_), subtype_(entry->subtype_), - xconnect_(entry->xconnect_) { + xconnect_(entry->xconnect_), + no_arp_(entry->no_arp_), + encap_type_(entry->encap_type_) { } InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, @@ -98,7 +100,9 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, vrf_id_(intf->vrf_id()), persistent_(false), subtype_(PhysicalInterface::INVALID), - xconnect_(NULL) { + xconnect_(NULL), + no_arp_(false), + encap_type_(PhysicalInterface::ETHERNET) { if (intf->flow_key_nh()) { flow_key_nh_id_ = intf->flow_key_nh()->id(); @@ -125,7 +129,16 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, if (sub_type_ == InetInterface::VHOST) { InterfaceKSyncEntry tmp(ksync_obj_, inet_intf->xconnect()); xconnect_ = ksync_obj_->GetReference(&tmp); + InterfaceKSyncEntry *xconnect = static_cast + (xconnect_.get()); + encap_type_ = xconnect->encap_type(); + no_arp_ = xconnect->no_arp(); } + } else if (type_ == Interface::PHYSICAL) { + const PhysicalInterface *physical_intf = + static_cast(intf); + encap_type_ = physical_intf->encap_type(); + no_arp_ = physical_intf->no_arp(); } } @@ -296,9 +309,29 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { subtype_ = phy_intf->subtype(); break; } - case Interface::INET: + case Interface::INET: { dmac = intf->mac(); + + bool no_arp = false; + PhysicalInterface::EncapType encap = PhysicalInterface::ETHERNET; + InterfaceKSyncEntry *xconnect = static_cast + (xconnect_.get()); + if (xconnect) { + no_arp = xconnect->no_arp(); + encap = xconnect->encap_type(); + } + + if (no_arp_ != no_arp) { + no_arp_ = no_arp; + ret = true; + } + if (encap_type_ != encap) { + encap_type_ = encap; + ret = true; + } + break; + } default: assert(0); } diff --git a/src/vnsw/agent/ksync/interface_ksync.h b/src/vnsw/agent/ksync/interface_ksync.h index 7222e074c52..ae5a3485128 100644 --- a/src/vnsw/agent/ksync/interface_ksync.h +++ b/src/vnsw/agent/ksync/interface_ksync.h @@ -53,6 +53,8 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { uint32_t interface_id() const {return interface_id_;} const string &interface_name() const {return interface_name_;} bool has_service_vlan() const {return has_service_vlan_;} + bool no_arp() const { return no_arp_; } + PhysicalInterface::EncapType encap_type() const { return encap_type_; } KSyncDBObject *GetObject(); virtual bool Sync(DBEntry *e); @@ -96,6 +98,8 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { bool persistent_; PhysicalInterface::SubType subtype_; KSyncEntryPtr xconnect_; + bool no_arp_; + PhysicalInterface::EncapType encap_type_; DISALLOW_COPY_AND_ASSIGN(InterfaceKSyncEntry); }; diff --git a/src/vnsw/agent/ksync/nexthop_ksync.cc b/src/vnsw/agent/ksync/nexthop_ksync.cc index c04009083eb..5aade68d748 100644 --- a/src/vnsw/agent/ksync/nexthop_ksync.cc +++ b/src/vnsw/agent/ksync/nexthop_ksync.cc @@ -459,18 +459,21 @@ bool NHKSyncEntry::Sync(DBEntry *e) { const TunnelNH *tun_nh = static_cast(e); const NextHop *active_nh = tun_nh->GetRt()->GetActiveNextHop(); - if (active_nh->GetType() != NextHop::ARP) { - valid_ = false; - interface_ = NULL; - dmac_.Zero(); - break; + if (active_nh->GetType() == NextHop::ARP) { + const ArpNH *arp_nh = static_cast(active_nh); + InterfaceKSyncObject *interface_object = + ksync_obj_->ksync()->interface_ksync_obj(); + InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface()); + interface_ = interface_object->GetReference(&if_ksync); + dmac_ = arp_nh->GetMac(); + } else if (active_nh->GetType() == NextHop::INTERFACE) { + const InterfaceNH *intf_nh = + static_cast(active_nh); + InterfaceKSyncObject *interface_object = + ksync_obj_->ksync()->interface_ksync_obj(); + InterfaceKSyncEntry if_ksync(interface_object, intf_nh->GetInterface()); + interface_ = interface_object->GetReference(&if_ksync); } - const ArpNH *arp_nh = static_cast(active_nh); - InterfaceKSyncObject *interface_object = - ksync_obj_->ksync()->interface_ksync_obj(); - InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface()); - interface_ = interface_object->GetReference(&if_ksync); - dmac_ = arp_nh->GetMac(); break; } @@ -630,7 +633,7 @@ int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { } encoder.set_nhr_encap_oif_id(intf_id); - SetEncap(NULL,encap); + SetEncap(if_ksync,encap); encoder.set_nhr_encap(encap); if (tunnel_type_.GetType() == TunnelType::MPLS_UDP) { flags |= NH_FLAG_TUNNEL_UDP_MPLS; @@ -958,6 +961,10 @@ void NHKSyncEntry::SetEncap(InterfaceKSyncEntry *if_ksync, return; } + if (if_ksync && if_ksync->encap_type() == PhysicalInterface::RAW_IP) { + return; + } + const MacAddress *smac = &MacAddress::ZeroMac(); /* DMAC encode */ for (size_t i = 0 ; i < dmac_.size(); i++) { diff --git a/src/vnsw/agent/ksync/vnswif_listener_base.cc b/src/vnsw/agent/ksync/vnswif_listener_base.cc index f90a08454b8..159b2ecaf76 100644 --- a/src/vnsw/agent/ksync/vnswif_listener_base.cc +++ b/src/vnsw/agent/ksync/vnswif_listener_base.cc @@ -334,7 +334,8 @@ void VnswInterfaceListenerBase::HandleAddressEvent(const Event *event) { agent_->set_vhost_prefix_len(event->plen_); InetInterface::CreateReq(agent_->interface_table(), agent_->vhost_interface_name(), - InetInterface::VHOST, agent_->fabric_vrf_name(), + InetInterface::VHOST, + agent_->fabric_vrf_name(), event->addr_, event->plen_, agent_->vhost_default_gateway(), Agent::NullString(), agent_->fabric_vrf_name()); diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index 54cd1edd949..1c6d9d70d50 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -15,6 +15,8 @@ //Forward declaration class AgentXmppChannel; +class InterfaceKey; +class PhysicalInterface; class Peer; class PathPreference { @@ -478,4 +480,21 @@ class DropRoute : public AgentRouteData { std::string vn_; DISALLOW_COPY_AND_ASSIGN(DropRoute); }; + +class Inet4UnicastInterfaceRoute : public AgentRouteData { +public: + Inet4UnicastInterfaceRoute(const PhysicalInterface *interface, + const std::string &vn_name); + virtual ~Inet4UnicastInterfaceRoute() { } + + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); + virtual std::string ToString() const {return "Interface";} + +private: + std::auto_ptr interface_key_; + std::string vn_name_; + DISALLOW_COPY_AND_ASSIGN(Inet4UnicastInterfaceRoute); +}; + #endif // vnsw_agent_path_hpp diff --git a/src/vnsw/agent/oper/inet_interface.cc b/src/vnsw/agent/oper/inet_interface.cc index 9986c06fc12..b85ac49d8bb 100644 --- a/src/vnsw/agent/oper/inet_interface.cc +++ b/src/vnsw/agent/oper/inet_interface.cc @@ -147,12 +147,24 @@ void InetInterface::DeActivateSimpleGateway() { // Add default route with given gateway static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, - const VrfEntry *vrf, const Ip4Address &gw, - const string &vn_name) { + const VrfEntry *vrf, const Interface *xconnect, + const Ip4Address &gw, const string &vn_name) { + + if (xconnect) { + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf->no_arp()) { + table->AddInterfaceRouteReq(agent, agent->local_peer(), + vrf->GetName(), Ip4Address(0), 0, + xconnect, vn_name); + return; + } + } table->AddGatewayRoute(agent->local_peer(), vrf->GetName(), Ip4Address(0), 0, gw, vn_name, MplsTable::kInvalidLabel, SecurityGroupList()); + return; } static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, @@ -166,12 +178,18 @@ static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, // - Resolve route for the subnet address static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, const VrfEntry *vrf, const string &interface, - const Ip4Address &addr, int plen, - const string &vn_name) { + const Interface *xconnect, const Ip4Address &addr, + int plen, const string &vn_name) { table->AddVHostRecvRoute(agent->local_peer(), vrf->GetName(), interface, addr, 32, vn_name, false); + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf && physical_intf->no_arp()) { + return; + } + table->AddVHostSubnetRecvRoute(agent->local_peer(), vrf->GetName(), interface, GetIp4SubnetBroadcastAddress(addr, plen), @@ -185,9 +203,15 @@ static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, } static void DeleteHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, - const VrfEntry *vrf, const Ip4Address &addr, - int plen) { + const VrfEntry *vrf, const Interface *xconnect, + const Ip4Address &addr, int plen) { table->Delete(agent->local_peer(), vrf->GetName(), addr, 32); + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf && physical_intf->no_arp()) { + return; + } + table->Delete(agent->local_peer(), vrf->GetName(), Address::GetIp4SubnetAddress(addr, plen), plen); table->Delete(agent->local_peer(), vrf->GetName(), @@ -210,20 +234,25 @@ void InetInterface::ActivateHostInterface() { InetUnicastAgentRouteTable *uc_rt_table = (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName())); if (ip_addr_.to_ulong()) { - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); } if (gw_.to_ulong()) { - AddDefaultRoute(agent, uc_rt_table, vrf(), gw_, vn_name_); + AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_, + vn_name_); } - // Add receive-route for broadcast address - Inet4MulticastAgentRouteTable *mc_rt_table = - static_cast - (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); - mc_rt_table->AddVHostRecvRoute(vrf()->GetName(), name_, - Ip4Address(0xFFFFFFFF), false); + const PhysicalInterface *physical_intf = + static_cast(xconnect_.get()); + if (physical_intf && physical_intf->no_arp() == false) { + // Add receive-route for broadcast address + Inet4MulticastAgentRouteTable *mc_rt_table = + static_cast + (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); + mc_rt_table->AddVHostRecvRoute(vrf()->GetName(), name_, + Ip4Address(0xFFFFFFFF), false); + } ReceiveNHKey nh_key(new InetInterfaceKey(name_), false); flow_key_nh_ = static_cast( agent->nexthop_table()->FindActiveEntry(&nh_key)); @@ -237,19 +266,24 @@ void InetInterface::DeActivateHostInterface() { InetUnicastAgentRouteTable *uc_rt_table = (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName())); if (ip_addr_.to_ulong()) { - DeleteHostRoutes(agent, uc_rt_table, vrf(), ip_addr_, plen_); + DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), ip_addr_, + plen_); } if (gw_.to_ulong()) { DeleteDefaultRoute(agent, uc_rt_table, vrf(), gw_); } - Inet4MulticastAgentRouteTable *mc_rt_table = - static_cast - (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); - // Add receive-route for broadcast address - mc_rt_table->Delete(vrf()->GetName(), Ip4Address(0), - Ip4Address(0xFFFFFFFF)); + const PhysicalInterface *physical_intf = + static_cast(xconnect_.get()); + if (physical_intf && physical_intf->no_arp() == false) { + Inet4MulticastAgentRouteTable *mc_rt_table = + static_cast + (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); + // Add receive-route for broadcast address + mc_rt_table->Delete(vrf()->GetName(), Ip4Address(0), + Ip4Address(0xFFFFFFFF)); + } // Delete receive nexthops ReceiveNH::Delete(agent->nexthop_table(), name_); @@ -270,7 +304,8 @@ InetInterface::InetInterface(const std::string &name, SubType sub_type, const Ip4Address &gw, Interface *xconnect, const std::string &vn_name) : Interface(Interface::INET, nil_uuid(), name, vrf), sub_type_(sub_type), - ip_addr_(ip_addr), plen_(plen), gw_(gw), xconnect_(xconnect), vn_name_(vn_name) { + ip_addr_(ip_addr), plen_(plen), gw_(gw), xconnect_(xconnect), + vn_name_(vn_name) { ipv4_active_ = false; l2_active_ = false; } @@ -343,7 +378,8 @@ bool InetInterface::OnChange(InetInterfaceData *data) { if (ip_addr_ != data->ip_addr_ || plen_ != data->plen_) { // Delete routes based on old ip-addr and prefix if (ip_addr_.to_ulong()) { - DeleteHostRoutes(agent, uc_rt_table, vrf(), ip_addr_, plen_); + DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), + ip_addr_, plen_); } ip_addr_ = data->ip_addr_; @@ -351,15 +387,15 @@ bool InetInterface::OnChange(InetInterfaceData *data) { vn_name_ = data->vn_name_; // Add routes for new ip-address and prefix if (data->ip_addr_.to_ulong()) { - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); } ret = true; } else if (vn_name_ != data->vn_name_) { // Change in vn_name, update route with new VN Name vn_name_ = data->vn_name_; - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); ret = true; } @@ -372,7 +408,8 @@ bool InetInterface::OnChange(InetInterfaceData *data) { gw_ = data->gw_; // Add route for new gateway if (gw_.to_ulong()) { - AddDefaultRoute(agent, uc_rt_table, vrf(), gw_, vn_name_); + AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_, + vn_name_); } ret = true; @@ -391,7 +428,8 @@ void InetInterface::CreateReq(InterfaceTable *table, const std::string &ifname, DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new InetInterfaceKey(ifname)); req.data.reset(new InetInterfaceData(sub_type, vrf_name, Ip4Address(addr), - plen, Ip4Address(gw), xconnect, vn_name)); + plen, Ip4Address(gw), xconnect, + vn_name)); table->Enqueue(&req); } diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 2e88ab94a9a..f34839cb810 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -685,6 +685,33 @@ bool Inet4UnicastGatewayRoute::AddChangePath(Agent *agent, AgentPath *path, return true; } +Inet4UnicastInterfaceRoute::Inet4UnicastInterfaceRoute +(const PhysicalInterface *interface, const std::string &vn_name) : + AgentRouteData(false), + interface_key_(new PhysicalInterfaceKey(interface->name())), + vn_name_(vn_name) { +} + +bool Inet4UnicastInterfaceRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { + bool ret = false; + + path->set_unresolved(false); + if (path->dest_vn_name() != agent->fabric_vn_name()) { + path->set_dest_vn_name(agent->fabric_vn_name()); + ret = true; + } + + InterfaceNHKey key(interface_key_->Clone(), false, InterfaceNHFlags::INET4); + NextHop *nh = static_cast + (agent->nexthop_table()->FindActiveEntry(&key)); + if (path->ChangeNH(agent, nh) == true) { + ret = true; + } + + return ret; +} + ///////////////////////////////////////////////////////////////////////////// // Sandesh functions ///////////////////////////////////////////////////////////////////////////// @@ -1346,3 +1373,21 @@ InetUnicastAgentRouteTable::AddSubnetRoute(const string &vrf_name, table->Process(req); } } + +void +InetUnicastAgentRouteTable::AddInterfaceRouteReq(Agent *agent, const Peer *peer, + const string &vrf_name, + const Ip4Address &ip, + uint8_t plen, + const Interface *interface, + const string &vn_name) { + + assert(interface->type() == Interface::PHYSICAL); + DBRequest rt_req(DBRequest::DB_ENTRY_ADD_CHANGE); + rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(), + vrf_name, ip, plen)); + const PhysicalInterface *phy_intf = static_cast + (interface); + rt_req.data.reset(new Inet4UnicastInterfaceRoute(phy_intf, vn_name)); + Inet4UnicastTableEnqueue(agent, &rt_req); +} diff --git a/src/vnsw/agent/oper/inet_unicast_route.h b/src/vnsw/agent/oper/inet_unicast_route.h index ee057610805..9fd542d208a 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.h +++ b/src/vnsw/agent/oper/inet_unicast_route.h @@ -287,6 +287,11 @@ class InetUnicastAgentRouteTable : public AgentRouteTable { void AddSubnetRoute(const string &vm_vrf, const IpAddress &addr, uint8_t plen, const string &vn_name, uint32_t vxlan_id); + void AddInterfaceRouteReq(Agent *agent, const Peer *peer, + const string &vrf_name, + const Ip4Address &ip, uint8_t plen, + const Interface *interface, + const std::string &vn_name); void AddClonedLocalPathReq(const Peer *peer, const string &vm_vrf, const IpAddress &addr, uint8_t plen, ClonedLocalPath *data); diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 57ae1a22046..90396b96be2 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -380,9 +380,10 @@ void PacketInterface::Delete(InterfaceTable *table, const std::string &ifname) { // Ethernet Interface routines ///////////////////////////////////////////////////////////////////////////// PhysicalInterface::PhysicalInterface(const std::string &name, VrfEntry *vrf, - SubType subtype) : + SubType subtype, EncapType encap, + bool no_arp) : Interface(Interface::PHYSICAL, nil_uuid(), name, vrf), - persistent_(false), subtype_(subtype) { + persistent_(false), subtype_(subtype), encap_type_(encap), no_arp_(no_arp) { if (subtype_ == VMWARE) persistent_ = true; } @@ -401,20 +402,25 @@ DBEntryBase::KeyPtr PhysicalInterface::GetDBRequestKey() const { return DBEntryBase::KeyPtr(key); } +void PhysicalInterface::Add() { +} + // Enqueue DBRequest to create a Host Interface void PhysicalInterface::CreateReq(InterfaceTable *table, const string &ifname, - const string &vrf_name, SubType subtype) { + const string &vrf_name, SubType subtype, + EncapType encap, bool no_arp) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype, encap, no_arp)); table->Enqueue(&req); } void PhysicalInterface::Create(InterfaceTable *table, const string &ifname, - const string &vrf_name, SubType subtype) { + const string &vrf_name, SubType subtype, + EncapType encap, bool no_arp) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype, encap, no_arp)); table->Process(req); } @@ -442,7 +448,8 @@ PhysicalInterfaceKey::~PhysicalInterfaceKey() { } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table) const { - return new PhysicalInterface(name_, NULL, PhysicalInterface::INVALID); + return new PhysicalInterface(name_, NULL, PhysicalInterface::INVALID, + PhysicalInterface::ETHERNET, false); } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, @@ -456,12 +463,14 @@ Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, const PhysicalInterfaceData *phy_data = static_cast(data); - return new PhysicalInterface(name_, vrf, phy_data->subtype_); + return new PhysicalInterface(name_, vrf, phy_data->subtype_, + phy_data->encap_type_, phy_data->no_arp_); } void PhysicalInterface::PostAdd() { - InterfaceTable *table = static_cast(get_table()); + InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); + InterfaceTable *table = static_cast(get_table()); if (subtype_ != VMWARE || table->agent()->test_mode()) { return; } @@ -490,13 +499,19 @@ void PhysicalInterface::PostAdd() { close(fd); } +void PhysicalInterface::Delete() { + InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); +} + InterfaceKey *PhysicalInterfaceKey::Clone() const { return new PhysicalInterfaceKey(*this); } PhysicalInterfaceData::PhysicalInterfaceData(const std::string &vrf_name, - PhysicalInterface::SubType subtype) - : InterfaceData(), subtype_(subtype) { + PhysicalInterface::SubType subtype, + PhysicalInterface::EncapType encap, + bool no_arp) + : InterfaceData(), subtype_(subtype), encap_type_(encap), no_arp_(no_arp) { EthInit(vrf_name); } diff --git a/src/vnsw/agent/oper/nexthop.cc b/src/vnsw/agent/oper/nexthop.cc index abd766752f6..1bc2b04755b 100644 --- a/src/vnsw/agent/oper/nexthop.cc +++ b/src/vnsw/agent/oper/nexthop.cc @@ -564,6 +564,24 @@ void InterfaceNH::CreatePacketInterfaceNh(const string &ifname) { NextHopTable::GetInstance()->Process(req); } +void InterfaceNH::CreatePhysicalInterfaceNh(const string &ifname, + const MacAddress &mac) { + DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); + req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname), false, + InterfaceNHFlags::INET4)); + req.data.reset(new InterfaceNHData(Agent::GetInstance()->fabric_vrf_name(), + mac)); + NextHopTable::GetInstance()->Process(req); +} + +void InterfaceNH::DeletePhysicalInterfaceNh(const string &ifname) { + DBRequest req(DBRequest::DB_ENTRY_DELETE); + req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname), false, + InterfaceNHFlags::INET4)); + req.data.reset(NULL); + NextHopTable::GetInstance()->Process(req); +} + void InterfaceNH::DeleteHostPortReq(const string &ifname) { DBRequest req; req.oper = DBRequest::DB_ENTRY_DELETE; diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index be4702fedc2..005abcaf35b 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -840,6 +840,9 @@ class InterfaceNH : public NextHop { static void DeleteNH(const uuid &intf_uuid, bool policy, uint8_t flags); static void DeleteVmInterfaceNHReq(const uuid &intf_uuid); static void CreatePacketInterfaceNh(const string &ifname); + static void CreatePhysicalInterfaceNh(const string &ifname, + const MacAddress &mac); + static void DeletePhysicalInterfaceNh(const string &ifname); static void DeleteHostPortReq(const string &ifname); static void CreateInetInterfaceNextHop(const string &ifname, const string &vrf_name); diff --git a/src/vnsw/agent/oper/physical_interface.h b/src/vnsw/agent/oper/physical_interface.h index 4cda1b90877..4df8fa1785e 100644 --- a/src/vnsw/agent/oper/physical_interface.h +++ b/src/vnsw/agent/oper/physical_interface.h @@ -17,13 +17,21 @@ class PhysicalInterface : public Interface { INVALID }; - PhysicalInterface(const std::string &name, VrfEntry *vrf, SubType subtype); + enum EncapType { + ETHERNET, // Ethernet with ARP + RAW_IP // No L2 header. Packets sent as raw-ip + }; + + PhysicalInterface(const std::string &name, VrfEntry *vrf, SubType subtype, + EncapType encap_type, bool no_arp); virtual ~PhysicalInterface(); bool CmpInterface(const DBEntry &rhs) const; std::string ToString() const { return "ETH <" + name() + ">"; } KeyPtr GetDBRequestKey() const; + virtual void Add(); + virtual void Delete(); void PostAdd(); SubType subtype() const { return subtype_; } @@ -32,24 +40,34 @@ class PhysicalInterface : public Interface { // Currently only vnware physical interface is persistent. // By default every physical interface is non-persistent. bool persistent() const {return persistent_;} + EncapType encap_type() const { return encap_type_; } + bool no_arp() const { return no_arp_; } // Helper functions static void CreateReq(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, SubType subtype); + const std::string &vrf_name, SubType subtype, + EncapType encap, bool no_arp); static void Create(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, SubType sub_type); + const std::string &vrf_name, SubType sub_type, + EncapType encap, bool no_arp); static void DeleteReq(InterfaceTable *table, const std::string &ifname); static void Delete(InterfaceTable *table, const std::string &ifname); private: bool persistent_; SubType subtype_; + EncapType encap_type_; + bool no_arp_; DISALLOW_COPY_AND_ASSIGN(PhysicalInterface); }; struct PhysicalInterfaceData : public InterfaceData { PhysicalInterfaceData(const std::string &vrf_name, - PhysicalInterface::SubType subtype); + PhysicalInterface::SubType subtype, + PhysicalInterface::EncapType encap, + bool no_arp); PhysicalInterface::SubType subtype_; + PhysicalInterface::EncapType encap_type_; + bool no_arp_; }; struct PhysicalInterfaceKey : public InterfaceKey { diff --git a/src/vnsw/agent/oper/test/test_inet_interface.cc b/src/vnsw/agent/oper/test/test_inet_interface.cc index 1ab3311201a..931e7412820 100644 --- a/src/vnsw/agent/oper/test/test_inet_interface.cc +++ b/src/vnsw/agent/oper/test/test_inet_interface.cc @@ -284,6 +284,87 @@ TEST_F(InetInterfaceTest, ll_basic_1) { client->WaitForIdle(); } +static void DelInetConfig(Agent *agent, const Ip4Address &addr, + const Ip4Address &gw, uint8_t plen) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), addr, 32, + NULL); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + gw, 32, NULL); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + addr, plen, NULL); + WAIT_FOR(1000, 1000, + (RouteGet(agent->fabric_vrf_name(), addr, plen) == NULL)); + client->WaitForIdle(); +} + +static void AddInetRoutes(Agent *agent) { + AgentParam *agent_param = client->param(); + AgentRouteTable *table = agent->fabric_inet4_unicast_table(); + InetInterface::CreateReq(agent->interface_table(), agent_param->vhost_name(), + InetInterface::VHOST, agent->fabric_vrf_name(), + agent_param->vhost_addr(), + agent_param->vhost_plen(), + agent_param->vhost_gw(), + agent_param->eth_port(), + agent->fabric_vrf_name()); + WAIT_FOR(1000, 1000, + (RouteGet(agent->fabric_vrf_name(), agent_param->vhost_addr(), + agent_param->vhost_plen()) != NULL)); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_encap_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + + // Cleanup routes added by old inet-interface + DelInetConfig(agent_, param->vhost_addr(), param->vhost_gw(), + param->vhost_plen()); + + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, 24, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent_->fabric_vrf_name(), ip, 32)) != NULL)); + if (rt != NULL) { + nh = rt->GetActiveNextHop(); + EXPECT_TRUE(nh->GetType() == NextHop::RECEIVE); + } + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent_->fabric_vrf_name(), net, 24)) != NULL)); + if (rt != NULL) { + nh = rt->GetActiveNextHop(); + EXPECT_TRUE(nh->GetType() == NextHop::RESOLVE); + } + + DelInetConfig(agent_, Ip4Address::from_string("10.10.10.10"), + Ip4Address::from_string("10.10.10.1"), 24); + + DelInterface(this, "vhost-1", agent_->fabric_vrf_name().c_str(), + "10.10.10.1"); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + + AddInetRoutes(agent_); + client->WaitForIdle(); +} + int main(int argc, char **argv) { GETUSERARGS(); diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index bbdeef66db4..f88b40c1f6e 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -545,7 +545,8 @@ AddPhysicalInterface(Agent *agent, IFMapNode *node) { ::PhysicalInterface::Create(intf_table, physical_interface->display_name(), agent->fabric_vrf_name(), - true); + ::PhysicalInterface::FABRIC, ::PhysicalInterface::ETHERNET, + false); ret = true; } diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.cc b/src/vnsw/agent/physical_devices/tables/physical_port.cc index 2cae4d5f266..1a50238cebc 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_port.cc @@ -74,7 +74,8 @@ bool PhysicalPortEntry::Copy(PhysicalPortTable *table, InterfaceTable *intf_table = table->agent()->interface_table(); PhysicalInterface::Create(intf_table, name_, table->agent()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); } } diff --git a/src/vnsw/agent/pkt/test/test_flowtable.cc b/src/vnsw/agent/pkt/test/test_flowtable.cc index 58621ea78db..78e67c7e730 100644 --- a/src/vnsw/agent/pkt/test/test_flowtable.cc +++ b/src/vnsw/agent/pkt/test/test_flowtable.cc @@ -490,7 +490,8 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), FlowTableTest::eth_itf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); } diff --git a/src/vnsw/agent/pkt/test/test_pkt.cc b/src/vnsw/agent/pkt/test/test_pkt.cc index 8e105dce6e0..8c97388feae 100644 --- a/src/vnsw/agent/pkt/test/test_pkt.cc +++ b/src/vnsw/agent/pkt/test/test_pkt.cc @@ -150,7 +150,8 @@ TEST_F(PktTest, FlowAdd_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "vnet0", Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); TxMplsPacket(2, "1.1.1.2", "10.1.1.1", 0, "2.2.2.2", "3.3.3.3", 1); diff --git a/src/vnsw/agent/pkt/test/test_pkt_flow.cc b/src/vnsw/agent/pkt/test/test_pkt_flow.cc index 5782331dcaa..ef31cc3f20c 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_flow.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_flow.cc @@ -3647,7 +3647,8 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_itf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_fip_cfg.cc b/src/vnsw/agent/test/test_fip_cfg.cc index ebd755ef4e4..b05ec15cafd 100644 --- a/src/vnsw/agent/test/test_fip_cfg.cc +++ b/src/vnsw/agent/test/test_fip_cfg.cc @@ -187,7 +187,8 @@ TEST_F(CfgTest, FloatingIp_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "enet1", Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); AddArp("10.1.1.2", "00:00:00:00:00:02", "enet1"); diff --git a/src/vnsw/agent/test/test_l2route.cc b/src/vnsw/agent/test/test_l2route.cc index 7ef3487aa61..996275c6ac0 100644 --- a/src/vnsw/agent/test/test_l2route.cc +++ b/src/vnsw/agent/test/test_l2route.cc @@ -84,7 +84,8 @@ class RouteTest : public ::testing::Test { PhysicalInterface::CreateReq(agent_->interface_table(), eth_name_, agent_->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_mirror.cc b/src/vnsw/agent/test/test_mirror.cc index cda26b5c9e0..dd67d636050 100644 --- a/src/vnsw/agent/test/test_mirror.cc +++ b/src/vnsw/agent/test/test_mirror.cc @@ -42,7 +42,8 @@ class MirrorTableTest : public ::testing::Test { nh_count_ = agent_->nexthop_table()->Size(); PhysicalInterface::CreateReq(agent_->interface_table(), eth_itf, agent_->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); fabric_gw_ip_ = Ip4Address::from_string("10.1.1.254"); uint16_t sport = 10000; unsigned long ip = 0x0a010102; diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index 524129a51bf..050301c9897 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -103,7 +103,8 @@ class RouteTest : public ::testing::Test { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_name_, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); diff --git a/src/vnsw/agent/test/test_vmport_cfg.cc b/src/vnsw/agent/test/test_vmport_cfg.cc index 6fd078a6a3d..02eaa2cefb0 100644 --- a/src/vnsw/agent/test/test_vmport_cfg.cc +++ b/src/vnsw/agent/test/test_vmport_cfg.cc @@ -1198,7 +1198,8 @@ TEST_F(CfgTest, Basic_1) { client->Reset(); PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), - eth_intf, vrf_name, PhysicalInterface::FABRIC); + eth_intf, vrf_name, PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); phy_intf = static_cast (agent_->interface_table()->FindActiveEntry(&key)); @@ -1206,7 +1207,8 @@ TEST_F(CfgTest, Basic_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_intf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); phy_intf = static_cast From 9b9b8351812de562ee8e79755f3a70c394134d60 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Thu, 6 Nov 2014 06:41:37 +0530 Subject: [PATCH 179/218] 1) Dont advertise non L2 multicast. 2) Add logical-interface policy in dependancy managaer to satisfy bidirectional check in dependancy tracker. Absence of this results in assert. --- src/vnsw/agent/controller/controller_export.cc | 3 +++ src/vnsw/agent/oper/ifmap_dependency_manager.cc | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/vnsw/agent/controller/controller_export.cc b/src/vnsw/agent/controller/controller_export.cc index 5ddb455e3c2..59a8fe98c1d 100644 --- a/src/vnsw/agent/controller/controller_export.cc +++ b/src/vnsw/agent/controller/controller_export.cc @@ -246,6 +246,9 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, bool route_can_be_dissociated = RouteCanDissociate(route); const Agent *agent = bgp_xmpp_peer->agent(); + if (route->GetTableType() != Agent::LAYER2) + return; + if (route_can_be_dissociated && (state != NULL)) { if ((state->exported_ == true) && !(agent->simulate_evpn_tor())) { AgentXmppChannel::ControllerSendMcastRouteDelete(bgp_xmpp_peer, diff --git a/src/vnsw/agent/oper/ifmap_dependency_manager.cc b/src/vnsw/agent/oper/ifmap_dependency_manager.cc index 659f41a674a..a5f75d2d260 100644 --- a/src/vnsw/agent/oper/ifmap_dependency_manager.cc +++ b/src/vnsw/agent/oper/ifmap_dependency_manager.cc @@ -136,6 +136,10 @@ void IFMapDependencyManager::Initialize() { list_of("virtual-machine-service-instance")); policy->insert(make_pair("virtual-machine", react_vm)); + ReactionMap react_li = map_list_of + (("logical-interface-virtual-machine-interface"), list_of("self")); + policy->insert(make_pair("logical-interface", react_li)); + ReactionMap react_vmi = map_list_of ("self", list_of("virtual-machine-interface-virtual-machine")) ("instance-ip-virtual-machine-interface", From 7d6ed8388eba3b1046bbc3ce11ca669424991792 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Fri, 7 Nov 2014 08:25:45 +0530 Subject: [PATCH 180/218] Fix encap change for composite NH. --- .../agent/controller/controller_export.cc | 2 +- src/vnsw/agent/oper/agent_path.cc | 23 +++++++++++++++--- src/vnsw/agent/oper/mpls.cc | 24 +++++++++++++------ src/vnsw/agent/oper/mpls.h | 2 ++ src/vnsw/agent/oper/multicast.cc | 6 +++-- src/vnsw/agent/oper/nexthop.cc | 13 +++++++++- src/vnsw/agent/oper/nexthop.h | 8 +++++++ .../physical_devices/tsn/tsn_vrf_listener.cc | 19 --------------- 8 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/vnsw/agent/controller/controller_export.cc b/src/vnsw/agent/controller/controller_export.cc index 59a8fe98c1d..af4b77a05c4 100644 --- a/src/vnsw/agent/controller/controller_export.cc +++ b/src/vnsw/agent/controller/controller_export.cc @@ -365,7 +365,7 @@ void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer, (bgp_xmpp_peer, route, active_path->NexthopIp(table->agent()), route->dest_vn_name(), state->label_, - TunnelType::AllType()); + TunnelType::GetTunnelBmap(state->tunnel_type_)); } else { state->evpn_exported_ = AgentXmppChannel::ControllerSendEvpnRouteDelete(bgp_xmpp_peer, diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index 62d2a1c8b5d..3e691aa7bd6 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -80,15 +80,29 @@ const NextHop* AgentPath::nexthop(Agent *agent) const { bool AgentPath::ChangeNH(Agent *agent, NextHop *nh) { // If NH is not found, point route to discard NH + bool ret = false; if (nh == NULL) { nh = agent->nexthop_table()->discard_nh(); } if (nh_ != nh) { nh_ = nh; - return true; + ret = true; } - return false; + + if ((peer_->GetType() == Peer::MULTICAST_PEER) && + (label_ != MplsTable::kInvalidLabel)) { + MplsLabelKey key(MplsLabel::MCAST_NH, label_); + MplsLabel *mpls = static_cast(agent->mpls_table()-> + FindActiveEntry(&key)); + ret = agent->mpls_table()->ChangeNH(mpls, nh); + if (mpls) { + //Send notify of change + mpls->get_table_partition()->Notify(mpls); + } + } + + return ret; } bool AgentPath::RebakeAllTunnelNHinCompositeNH(const AgentRoute *sync_route) { @@ -167,7 +181,10 @@ bool AgentPath::UpdateNHPolicy(Agent *agent) { } bool AgentPath::UpdateTunnelType(Agent *agent, const AgentRoute *sync_route) { - if (tunnel_type_ == TunnelType::ComputeType(tunnel_bmap_)) { + //Return if there is no change in tunnel type for non Composite NH. + //For composite NH component needs to be traversed. + if ((tunnel_type_ == TunnelType::ComputeType(tunnel_bmap_)) && + (nh_.get() && nh_.get()->GetType() != NextHop::COMPOSITE)) { return false; } diff --git a/src/vnsw/agent/oper/mpls.cc b/src/vnsw/agent/oper/mpls.cc index 05dbd945760..c54f5b20a4f 100644 --- a/src/vnsw/agent/oper/mpls.cc +++ b/src/vnsw/agent/oper/mpls.cc @@ -65,6 +65,19 @@ bool MplsTable::OnChange(DBEntry *entry, const DBRequest *req) { return ret; } +bool MplsTable::ChangeNH(MplsLabel *mpls, NextHop *nh) { + if (mpls == NULL) + return false; + + if (mpls->nh_ != nh) { + mpls->nh_ = nh; + assert(nh); + mpls->SyncDependentPath(); + return true; + } + return false; +} + // No Change expected for MPLS Label bool MplsTable::ChangeHandler(MplsLabel *mpls, const DBRequest *req) { bool ret = false; @@ -77,13 +90,7 @@ bool MplsTable::ChangeHandler(MplsLabel *mpls, const DBRequest *req) { nh = static_cast (agent()->nexthop_table()->FindActiveEntry(&key)); } - - if (mpls->nh_ != nh) { - mpls->nh_ = nh; - assert(nh); - mpls->SyncDependentPath(); - ret = true; - } + ret = ChangeNH(mpls, nh); return ret; } @@ -163,6 +170,9 @@ void MplsLabel::CreateVPortLabel(uint32_t label, const uuid &intf_uuid, void MplsLabel::CreateMcastLabelReq(uint32_t label, COMPOSITETYPE type, ComponentNHKeyList &component_nh_key_list, const std::string vrf_name) { + if (label == 0 || label == MplsTable::kInvalidLabel) + return; + DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; diff --git a/src/vnsw/agent/oper/mpls.h b/src/vnsw/agent/oper/mpls.h index 843d596796f..91989c53f1f 100644 --- a/src/vnsw/agent/oper/mpls.h +++ b/src/vnsw/agent/oper/mpls.h @@ -151,6 +151,8 @@ class MplsTable : public AgentDBTable { static DBTableBase *CreateTable(DB *db, const std::string &name); static MplsTable *GetInstance() {return mpls_table_;}; void Process(DBRequest &req); + bool ChangeNH(MplsLabel *mpls, NextHop *nh); + private: static MplsTable *mpls_table_; bool ChangeHandler(MplsLabel *mpls, const DBRequest *req); diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index c0a45cff993..5ed0f8a423d 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -77,11 +77,12 @@ void MulticastHandler::AddL2BroadcastRoute(MulticastGroupObject *obj, GetInterfaceComponentNHKeyList(obj, InterfaceNHFlags::LAYER2); if (component_nh_key_list.size() == 0) return; + uint32_t route_tunnel_bmap = TunnelType::AllType(); Layer2AgentRouteTable::AddLayer2BroadcastRoute(agent_->local_vm_peer(), vrf_name, vn_name, label, vxlan_id, ethernet_tag, - TunnelType::AllType(), + route_tunnel_bmap, Composite::L2INTERFACE, component_nh_key_list); RebakeSubnetRoute(agent_->local_vm_peer(), vrf_name, label, @@ -476,13 +477,14 @@ void MulticastHandler::TriggerLocalRouteChange(MulticastGroupObject *obj, obj->GetGroupAddress().to_string(), component_nh_key_list.size()); //Add Layer2 FF:FF:FF:FF:FF:FF, local_vm_peer + uint32_t route_tunnel_bmap = TunnelType::AllType(); Layer2AgentRouteTable::AddLayer2BroadcastRoute(peer, obj->vrf_name(), obj->GetVnName(), obj->evpn_mpls_label(), obj->vxlan_id(), 0, - TunnelType::AllType(), + route_tunnel_bmap, Composite::L2INTERFACE, component_nh_key_list); } diff --git a/src/vnsw/agent/oper/nexthop.cc b/src/vnsw/agent/oper/nexthop.cc index b378d7f086c..938e929f69f 100644 --- a/src/vnsw/agent/oper/nexthop.cc +++ b/src/vnsw/agent/oper/nexthop.cc @@ -1432,6 +1432,12 @@ void CompositeNH::ChangeComponentNHKeyTunnelType( if ((*it)->nh_key()->GetType() == NextHop::COMPOSITE) { CompositeNHKey *composite_nh_key = static_cast((*it)->nh_key()->Clone()); + if (composite_nh_key->composite_nh_type() == Composite::TOR) { + type = TunnelType::VXLAN; + } + if (composite_nh_key->composite_nh_type() == Composite::FABRIC) { + type = TunnelType::ComputeType(TunnelType::MplsType()); + } ChangeComponentNHKeyTunnelType( composite_nh_key->component_nh_key_list_, type); std::auto_ptr nh_key(composite_nh_key); @@ -1458,13 +1464,18 @@ void CompositeNH::ChangeComponentNHKeyTunnelType( //would call ChangeTunnelType() API which would result in recursion CompositeNH *CompositeNH::ChangeTunnelType(Agent *agent, TunnelType::Type type) const { + if (composite_nh_type_ == Composite::TOR) { + type = TunnelType::VXLAN; + } + if (composite_nh_type_ == Composite::FABRIC) { + type = TunnelType::ComputeType(TunnelType::MplsType()); + } //Create all component NH with new tunnel type CreateComponentNH(agent, type); //Change the tunnel type of all component NH key ComponentNHKeyList new_component_nh_key_list = component_nh_key_list_; ChangeComponentNHKeyTunnelType(new_component_nh_key_list, type); - //Create the new nexthop CompositeNHKey *comp_nh_key = new CompositeNHKey(composite_nh_type_, policy_, diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index e4c607b7d2e..708404b4d65 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -293,6 +293,13 @@ class TunnelType { static TypeBmap DefaultTypeBmap() {return (1 << DefaultType());} static TypeBmap VxlanType() {return (1 << VXLAN);}; static TypeBmap MplsType() {return ((1 << MPLS_GRE) | (1 << MPLS_UDP));}; + static TypeBmap GetTunnelBmap(TunnelType::Type type) { + if (type == MPLS_GRE || type == MPLS_UDP) + return TunnelType::MplsType(); + if (type == VXLAN) + return TunnelType::VxlanType(); + return TunnelType::AllType(); + } static TypeBmap AllType() {return ((1 << MPLS_GRE) | (1 << MPLS_UDP) | (1 << VXLAN));} static TypeBmap GREType() {return (1 << MPLS_GRE);} @@ -1120,6 +1127,7 @@ class CompositeNHKey : public NextHopKey { void CreateTunnelNH(Agent *agent); void CreateTunnelNHReq(Agent *agent); void ChangeTunnelType(TunnelType::Type tunnel_type); + COMPOSITETYPE composite_nh_type() const {return composite_nh_type_;} private: friend class CompositeNH; void ExpandLocalCompositeNH(Agent *agent); diff --git a/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc index 1b9cfe4639e..abacb885fd1 100644 --- a/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc +++ b/src/vnsw/agent/physical_devices/tsn/tsn_vrf_listener.cc @@ -37,23 +37,4 @@ void TsnVrfListener::VrfNotify(DBEntryBase *entry) { address, "pkt0", true); } - - //Add TSN route - boost::system::error_code ec; - IpAddress tsn_addr = IpAddress::from_string(agent_->tsn_ip_1(), ec).to_v4(); - IpAddress tsn_gw_addr = IpAddress::from_string(agent_->tsn_ip_2(), ec).to_v4(); - SecurityGroupList sg; - PathPreference pref; - ControllerVmRoute *data = - ControllerVmRoute::MakeControllerVmRoute(agent_->local_peer(), - Agent::GetInstance()->fabric_vrf_name(), - Agent::GetInstance()->router_id(), - Agent::GetInstance()->fabric_vrf_name(), - tsn_gw_addr.to_v4(), TunnelType::VxlanType(), - 4, "", sg, pref); - - InetUnicastAgentRouteTable::AddRemoteVmRouteReq(agent_->local_peer(), - Agent::GetInstance()->fabric_vrf_name(), - tsn_addr, 32, - data); } From 2833ae5a2cf0b8fc20e66e327534b9060e91f8d1 Mon Sep 17 00:00:00 2001 From: Hari Date: Thu, 6 Nov 2014 22:23:53 -0800 Subject: [PATCH 181/218] 1. Send GW in DHCP response (not set it to service address) 2. Remove the exception case from the api server changes for service address --- src/config/api-server/vnc_addr_mgmt.py | 2 -- src/vnsw/agent/pkt/pkt_handler.cc | 8 +++++--- src/vnsw/agent/services/dhcp_handler.cc | 2 +- src/vnsw/agent/services/dhcpv6_handler.cc | 2 +- src/vnsw/agent/services/icmp_handler.cc | 3 ++- src/vnsw/agent/services/services_sandesh.cc | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/config/api-server/vnc_addr_mgmt.py b/src/config/api-server/vnc_addr_mgmt.py index 51249b9308c..e38b42b4ddd 100644 --- a/src/config/api-server/vnc_addr_mgmt.py +++ b/src/config/api-server/vnc_addr_mgmt.py @@ -480,8 +480,6 @@ def net_update_req(self, vn_fq_name, db_vn_dict, req_vn_dict, obj_uuid=None): req_subnet['enable_dhcp'] = True if (req_subnet['gw'] != db_subnet['gw']): raise AddrMgmtSubnetInvalid(vn_fq_name_str, key) - if (req_subnet['dns_server_address'] != db_subnet['dns_server_address']): - raise AddrMgmtSubnetInvalid(vn_fq_name_str, key) req_alloc_list = req_subnet['allocation_pools'] or [] db_alloc_list = db_subnet['allocation_pools'] or [] diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index cccffe3d88e..db883e6f8a3 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -125,7 +125,7 @@ void PktHandler::HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff){ if (pkt_info->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) { // In case of a control packet from a TOR served by us, the ifindex // is modified to index of the VM interface; validate this interface. - if (!IsValidInterface(hdr.ifindex, &intf)) { + if (!IsValidInterface(pkt_info->agent_hdr.ifindex, &intf)) { goto drop; } } @@ -586,14 +586,16 @@ bool PktHandler::IsGwPacket(const Interface *intf, const IpAddress &dst_ip) { } if (IsIp4SubnetMember(vm_intf->ip_addr(), ipam[i].ip_prefix.to_v4(), ipam[i].plen)) - return (ipam[i].default_gw == dst_ip); + return (ipam[i].default_gw == dst_ip || + ipam[i].dns_server == dst_ip); } else { if (!ipam[i].IsV6()) { continue; } if (IsIp6SubnetMember(vm_intf->ip6_addr(), ipam[i].ip_prefix.to_v6(), ipam[i].plen)) - return (ipam[i].default_gw == dst_ip); + return (ipam[i].default_gw == dst_ip || + ipam[i].dns_server == dst_ip); } } diff --git a/src/vnsw/agent/services/dhcp_handler.cc b/src/vnsw/agent/services/dhcp_handler.cc index 285cf739460..63acc2c5f06 100644 --- a/src/vnsw/agent/services/dhcp_handler.cc +++ b/src/vnsw/agent/services/dhcp_handler.cc @@ -582,7 +582,7 @@ bool DhcpHandler::FindLeaseData() { Ip4Address service_address = ipam[i].dns_server.to_v4(); if (service_address.is_unspecified()) service_address = default_gw; - FillDhcpInfo(ip, ipam[i].plen, service_address, service_address); + FillDhcpInfo(ip, ipam[i].plen, default_gw, service_address); return true; } } diff --git a/src/vnsw/agent/services/dhcpv6_handler.cc b/src/vnsw/agent/services/dhcpv6_handler.cc index 8c67db5acad..ee615c75a72 100644 --- a/src/vnsw/agent/services/dhcpv6_handler.cc +++ b/src/vnsw/agent/services/dhcpv6_handler.cc @@ -481,7 +481,7 @@ bool Dhcpv6Handler::FindLeaseData() { Ip6Address service_address = ipam[i].dns_server.to_v6(); if (service_address.is_unspecified()) service_address = default_gw; - FillDhcpInfo(ip, ipam[i].plen, service_address, service_address); + FillDhcpInfo(ip, ipam[i].plen, default_gw, service_address); return true; } } diff --git a/src/vnsw/agent/services/icmp_handler.cc b/src/vnsw/agent/services/icmp_handler.cc index f41e81cd656..27a92fb1254 100644 --- a/src/vnsw/agent/services/icmp_handler.cc +++ b/src/vnsw/agent/services/icmp_handler.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ void IcmpHandler::SendResponse(VmInterface *vm_intf) { memcpy(icmp_payload, icmp_, icmp_len_); // Retain the agent-header before ethernet header - uint16_t len = (char *)pkt_info_->eth - (char *)pkt_info_->pkt; + uint16_t len = EncapHeaderLen(); // Form ICMP Packet with following // EthHdr - IP Header - ICMP Header diff --git a/src/vnsw/agent/services/services_sandesh.cc b/src/vnsw/agent/services/services_sandesh.cc index 6a35d7d6c02..37bcdafb539 100644 --- a/src/vnsw/agent/services/services_sandesh.cc +++ b/src/vnsw/agent/services/services_sandesh.cc @@ -263,7 +263,7 @@ uint16_t ServicesSandesh::FillVrouterHdr(PktTrace::Pkt &pkt, VrouterHdr &resp) { { { "switch", "route", "arp", "l2-protocol", "trap-nexthop", "trap-resolve", "trap-flow-miss", "trap-l3-protocol", "trap-diag", "trap-ecmp-resolve", "trap_source_mismatch", - "trap-dont-fragment" } }; + "trap-dont-fragment", "tor-control" } }; uint8_t *ptr = pkt.pkt; AgentHdr *hdr = reinterpret_cast(ptr); resp.ifindex = hdr->ifindex; From 6e7a4d3bab6ecf3537e94dce37a17b55ec65c5d6 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Fri, 7 Nov 2014 03:26:35 -0800 Subject: [PATCH 182/218] Fix VN and VMI order dependency. Since VN object can be created after VMI, we need to wait for VN in VMI to become available before programming vlan port bindings. Adding Sandesh trace for unresolved references. --- src/ksync/ksync_object.cc | 3 +- src/ksync/ksync_object.h | 2 +- .../ovs_tor_agent/ovsdb_client/SConscript | 11 +- .../ovsdb_client/ovsdb_client.cc | 12 +- .../ovs_tor_agent/ovsdb_client/ovsdb_client.h | 7 +- .../ovsdb_client/ovsdb_client_idl.cc | 12 ++ .../ovsdb_client/ovsdb_client_idl.h | 5 + .../ovsdb_client/ovsdb_client_session.h | 2 + .../ovsdb_client/ovsdb_client_tcp.cc | 5 + .../ovsdb_client/ovsdb_client_tcp.h | 1 + .../ovs_tor_agent/ovsdb_client/ovsdb_entry.h | 2 +- .../ovsdb_client/vlan_port_binding_ovsdb.cc | 65 ++++++++--- .../ovsdb_client/vlan_port_binding_ovsdb.h | 1 + .../ovsdb_client/vm_interface_ksync.cc | 106 ++++++++++++++++++ .../ovsdb_client/vm_interface_ksync.h | 56 +++++++++ 15 files changed, 262 insertions(+), 28 deletions(-) create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc create mode 100644 src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index 0617b9faeb1..cf3da5dac18 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -1134,8 +1134,9 @@ KSyncObjectManager::~KSyncObjectManager() { SandeshTraceBufferPtr KSyncTraceBuf(SandeshTraceBufferCreate("KSync", 1000)); -void KSyncObjectManager::Init() { +KSyncObjectManager *KSyncObjectManager::Init() { singleton_ = new KSyncObjectManager(); + return singleton_; } void KSyncObjectManager::Shutdown() { diff --git a/src/ksync/ksync_object.h b/src/ksync/ksync_object.h index d3cd2ba3fb5..cadb0070c29 100644 --- a/src/ksync/ksync_object.h +++ b/src/ksync/ksync_object.h @@ -221,7 +221,7 @@ class KSyncObjectManager { bool Process(KSyncObjectEvent *event); void Enqueue(KSyncObjectEvent *event); KSyncEntry *default_defer_entry(); - static void Init(); + static KSyncObjectManager *Init(); static void Shutdown(); static void Unregister(KSyncObject *); private: diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript index dfe7b794fa4..068f3aba6ec 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/SConscript @@ -22,7 +22,7 @@ sandesh_objs = AgentEnv.BuildExceptionCppObj(env, SandeshGenSrcs) libovsdbclient = env.Library('ovsdbclient', sandesh_objs + [ - 'ovsdb_wrapper.c', + 'logical_switch_ovsdb.cc', 'ovsdb_client.cc', 'ovsdb_client_idl.cc', 'ovsdb_client_session.cc', @@ -31,13 +31,14 @@ libovsdbclient = env.Library('ovsdbclient', 'ovsdb_object.cc', 'ovsdb_route_data.cc', 'ovsdb_route_peer.cc', - 'physical_switch_ovsdb.cc', - 'logical_switch_ovsdb.cc', - 'physical_port_ovsdb.cc', - 'vlan_port_binding_ovsdb.cc', + 'ovsdb_wrapper.c', 'physical_locator_ovsdb.cc', + 'physical_port_ovsdb.cc', + 'physical_switch_ovsdb.cc', 'unicast_mac_local_ovsdb.cc', 'unicast_mac_remote_ovsdb.cc', + 'vlan_port_binding_ovsdb.cc', + 'vm_interface_ksync.cc' ]) env.Requires(libovsdbclient, '#/build/include/openvswitch/include') diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc index 1377e868ad5..2ab6b5b0dfb 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.cc @@ -12,12 +12,22 @@ using OVSDB::OvsdbClient; +OvsdbClient::OvsdbClient(OvsPeerManager *manager) : peer_manager_(manager), + ksync_obj_manager_(KSyncObjectManager::Init()){ +} + +OvsdbClient::~OvsdbClient() { +} + +KSyncObjectManager *OvsdbClient::ksync_obj_manager() { + return ksync_obj_manager_; +} + void OvsdbClient::Init() { } OvsdbClient *OvsdbClient::Allocate(Agent *agent, TorAgentParam *params, OvsPeerManager *manager) { - KSyncObjectManager::Init(); return (new OvsdbClientTcp(agent, params, manager)); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h index 2ecc07b074c..6e8297c6d44 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h @@ -9,24 +9,27 @@ class TorAgentParam; class SandeshOvsdbClient; class OvsPeerManager; +class KSyncObjectManager; namespace OVSDB { class OvsdbClient { public: - OvsdbClient(OvsPeerManager *manager) : peer_manager_(manager) {} - virtual ~OvsdbClient() {} + OvsdbClient(OvsPeerManager *manager); + virtual ~OvsdbClient(); virtual void RegisterClients() = 0; virtual const std::string protocol() = 0; virtual const std::string server() = 0; virtual uint16_t port() = 0; virtual Ip4Address tsn_ip() = 0; virtual void AddSessionInfo(SandeshOvsdbClient &client) = 0; + KSyncObjectManager *ksync_obj_manager(); void Init(); static OvsdbClient* Allocate(Agent *agent, TorAgentParam *params, OvsPeerManager *manager); protected: OvsPeerManager *peer_manager_; private: + KSyncObjectManager *ksync_obj_manager_; DISALLOW_COPY_AND_ASSIGN(OvsdbClient); }; }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 88bdd352dbe..60f795b2e2f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -23,6 +23,7 @@ extern "C" { #include #include #include +#include #include @@ -38,6 +39,7 @@ class PhysicalDeviceVnTable; using OVSDB::OvsdbClientIdl; using OVSDB::OvsdbClientSession; using OVSDB::OvsdbEntryBase; +using OVSDB::VMInterfaceKSyncObject; using OVSDB::PhysicalSwitchTable; using OVSDB::LogicalSwitchTable; using OVSDB::PhysicalPortTable; @@ -81,6 +83,8 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent, callback_[i] = NULL; } route_peer_.reset(manager->Allocate(IpAddress())); + vm_interface_table_.reset(new VMInterfaceKSyncObject(this, + (DBTable *)agent->interface_table())); physical_switch_table_.reset(new PhysicalSwitchTable(this)); logical_switch_table_.reset(new LogicalSwitchTable(this, (DBTable *)agent->device_manager()->physical_device_vn_table())); @@ -159,10 +163,18 @@ Ip4Address OvsdbClientIdl::tsn_ip() { return session_->tsn_ip(); } +KSyncObjectManager *OvsdbClientIdl::ksync_obj_manager() { + return session_->ksync_obj_manager(); +} + OvsPeer *OvsdbClientIdl::route_peer() { return route_peer_.get(); } +VMInterfaceKSyncObject *OvsdbClientIdl::vm_interface_table() { + return vm_interface_table_.get(); +} + PhysicalSwitchTable *OvsdbClientIdl::physical_switch_table() { return physical_switch_table_.get(); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 6c942233334..0e3103d63be 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -19,9 +19,11 @@ do {\ class OvsPeer; class OvsPeerManager; +class KSyncObjectManager; namespace OVSDB { class OvsdbClientSession; +class VMInterfaceKSyncObject; class PhysicalSwitchTable; class LogicalSwitchTable; class PhysicalPortTable; @@ -73,8 +75,10 @@ class OvsdbClientIdl { // Get TOR Service Node IP Ip4Address tsn_ip(); + KSyncObjectManager *ksync_obj_manager(); OvsPeer *route_peer(); Agent *agent() {return agent_;} + VMInterfaceKSyncObject *vm_interface_table(); PhysicalSwitchTable *physical_switch_table(); LogicalSwitchTable *logical_switch_table(); PhysicalPortTable *physical_port_table(); @@ -92,6 +96,7 @@ class OvsdbClientIdl { NotifyCB callback_[OVSDB_TYPE_COUNT]; PendingTxnMap pending_txn_; std::auto_ptr route_peer_; + std::auto_ptr vm_interface_table_; std::auto_ptr physical_switch_table_; std::auto_ptr logical_switch_table_; std::auto_ptr physical_port_table_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h index ce492de5296..4c4381d978d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h @@ -12,6 +12,7 @@ class OvsPeer; class OvsPeerManager; +class KSyncObjectManager; namespace OVSDB { class OvsdbClientIdl; @@ -20,6 +21,7 @@ class OvsdbClientSession { OvsdbClientSession(Agent *agent, OvsPeerManager *manager); virtual ~OvsdbClientSession(); + virtual KSyncObjectManager *ksync_obj_manager() = 0; virtual Ip4Address tsn_ip() = 0; virtual void SendMsg(u_int8_t *buf, std::size_t len) = 0; void MessageProcess(const u_int8_t *buf, std::size_t len); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc index 0412d4e8a33..296598bfc54 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -127,6 +127,11 @@ bool OvsdbClientTcpSession::ReceiveDequeue(queue_msg msg) { return true; } +KSyncObjectManager *OvsdbClientTcpSession::ksync_obj_manager() { + OvsdbClientTcp *ovs_server = static_cast(server()); + return ovs_server->ksync_obj_manager(); +} + Ip4Address OvsdbClientTcpSession::tsn_ip() { OvsdbClientTcp *ovs_server = static_cast(server()); return ovs_server->tsn_ip(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h index a8d4533eff7..590c0169238 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -56,6 +56,7 @@ class OvsdbClientTcpSession : public OvsdbClientSession, public TcpSession { // Dequeue received message from workqueue for processing bool ReceiveDequeue(queue_msg msg); + KSyncObjectManager *ksync_obj_manager(); Ip4Address tsn_ip(); void set_status(std::string status) {status_ = status;} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h index df700bf6ed9..0cae512595f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.h @@ -68,7 +68,7 @@ class OvsdbDBEntry : public KSyncDBEntry, public OvsdbEntryBase { bool Change(); bool Delete(); - bool IsDataResolved(); + virtual bool IsDataResolved(); bool IsDelAckWaiting(); bool IsAddChangeAckWaiting(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index 2cdb0c1eda7..adef6a846f5 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -9,6 +9,7 @@ extern "C" { #include #include #include +#include #include #include @@ -27,21 +28,15 @@ using OVSDB::LogicalSwitchEntry; VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_), - logical_switch_name_("") { - if (entry->vm_interface() && entry->vm_interface()->vn()) - logical_switch_name_ = - UuidToString(entry->vm_interface()->vn()->GetUuid()); - physical_port_name_ = entry->physical_port()->name(); - physical_device_name_ = entry->physical_port()->device()->name(); - vlan_ = entry->vlan(); + logical_switch_name_(), physical_port_name_(entry->physical_port()->name()), + physical_device_name_(entry->physical_port()->device()->name()), + vlan_(entry->vlan()) { } VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, - const VlanPortBindingEntry *key) : OvsdbDBEntry(table) { - logical_switch_name_ = key->logical_switch_name_; - physical_port_name_ = key->physical_port_name_; - physical_device_name_ = key->physical_device_name_; - vlan_ = key->vlan_; + const VlanPortBindingEntry *key) : OvsdbDBEntry(table), + physical_port_name_(key->physical_port_name_), + physical_device_name_(key->physical_device_name_), vlan_(key->vlan_) { } void VlanPortBindingEntry::PreAddChange() { @@ -106,15 +101,29 @@ void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { bool VlanPortBindingEntry::Sync(DBEntry *db_entry) { AGENT::VlanLogicalPortEntry *entry = static_cast(db_entry); - std::string ls_name(""); + std::string ls_name; + boost::uuids::uuid vmi_uuid; + bool change = false; + + if (entry->vm_interface()) { + vmi_uuid = entry->vm_interface()->GetUuid(); + } + if (entry->vm_interface() && entry->vm_interface()->vn()) { ls_name = UuidToString(entry->vm_interface()->vn()->GetUuid()); } + + if (vmi_uuid_ != vmi_uuid) { + vmi_uuid_ = vmi_uuid; + change = true; + } + if (ls_name != logical_switch_name_) { logical_switch_name_ = ls_name; - return true; + change = true; } - return false; + + return change; } bool VlanPortBindingEntry::IsLess(const KSyncEntry &entry) const { @@ -133,26 +142,48 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { PhysicalPortEntry *p_port = static_cast(p_table->GetReference(&key)); if (!p_port->IsResolved()) { + OVSDB_TRACE(Trace, "Physical Port unavailable for Port Vlan Binding " + + physical_port_name_ + " vlan " + integerToString(vlan_) + + " to Logical Switch " + logical_switch_name_); return p_port; } + PhysicalSwitchTable *ps_table = table_->client_idl()->physical_switch_table(); PhysicalSwitchEntry ps_key(ps_table, physical_device_name_.c_str()); PhysicalSwitchEntry *p_switch = static_cast(ps_table->GetReference(&ps_key)); if (!p_switch->IsResolved()) { + OVSDB_TRACE(Trace, "Physical Switch unavailable for Port Vlan Binding "+ + physical_port_name_ + " vlan " + integerToString(vlan_) + + " to Logical Switch " + logical_switch_name_); return p_switch; } - if (logical_switch_name_.empty()) { - return NULL; + + VMInterfaceKSyncObject *vm_intf_table = + table_->client_idl()->vm_interface_table(); + VMInterfaceKSyncEntry vm_intf_key(vm_intf_table, vmi_uuid_); + VMInterfaceKSyncEntry *vm_intf = static_cast( + vm_intf_table->GetReference(&vm_intf_key)); + if (!vm_intf->IsResolved()) { + OVSDB_TRACE(Trace, "VM Interface unavailable for Port Vlan Binding " + + physical_port_name_ + " vlan " + integerToString(vlan_) + + " to Logical Switch " + logical_switch_name_); + return vm_intf; } + + assert(!logical_switch_name_.empty()); LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); LogicalSwitchEntry *ls_entry = static_cast(l_table->GetReference(&ls_key)); if (!ls_entry->IsResolved()) { + OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan Binding "+ + physical_port_name_ + " vlan " + integerToString(vlan_) + + " to Logical Switch " + logical_switch_name_); return ls_entry; } + return NULL; } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h index 46d82f2a608..637b46654cd 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h @@ -54,6 +54,7 @@ class VlanPortBindingEntry : public OvsdbDBEntry { std::string physical_port_name_; std::string physical_device_name_; uint16_t vlan_; + boost::uuids::uuid vmi_uuid_; DISALLOW_COPY_AND_ASSIGN(VlanPortBindingEntry); }; }; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc new file mode 100644 index 00000000000..0213c31e3fc --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +extern "C" { +#include +}; +#include + +#include +#include +#include +#include + +using OVSDB::OvsdbDBEntry; +using OVSDB::VMInterfaceKSyncEntry; +using OVSDB::VMInterfaceKSyncObject; + +VMInterfaceKSyncEntry::VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + const VmInterface *entry) : OvsdbDBEntry(table_), + uuid_(entry->GetUuid()) { +} + +VMInterfaceKSyncEntry::VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + const VMInterfaceKSyncEntry *key) : OvsdbDBEntry(table), + uuid_(key->uuid_) { +} + +VMInterfaceKSyncEntry::VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + boost::uuids::uuid uuid) : OvsdbDBEntry(table), uuid_(uuid) { +} + +void VMInterfaceKSyncEntry::AddMsg(struct ovsdb_idl_txn *txn) { +} + +void VMInterfaceKSyncEntry::ChangeMsg(struct ovsdb_idl_txn *txn) { +} + +void VMInterfaceKSyncEntry::DeleteMsg(struct ovsdb_idl_txn *txn) { +} + +bool VMInterfaceKSyncEntry::Sync(DBEntry *db_entry) { + VmInterface *entry = static_cast(db_entry); + + std::string vn_name; + if (entry->vn()) { + vn_name = UuidToString(entry->vn()->GetUuid()); + } + if (vn_name_ != vn_name) { + vn_name_ = vn_name; + return true; + } + return false; +} + +bool VMInterfaceKSyncEntry::IsLess(const KSyncEntry &entry) const { + const VMInterfaceKSyncEntry &intf_entry = + static_cast(entry); + return uuid_ < intf_entry.uuid_; +} + +KSyncEntry *VMInterfaceKSyncEntry::UnresolvedReference() { + if (vn_name_.empty()) { + return table_->client_idl()->ksync_obj_manager()->default_defer_entry(); + } + return NULL; +} + +VMInterfaceKSyncObject::VMInterfaceKSyncObject(OvsdbClientIdl *idl, DBTable *table) : + OvsdbDBObject(idl, table) { +} + +VMInterfaceKSyncObject::~VMInterfaceKSyncObject() { +} + +void VMInterfaceKSyncObject::OvsdbNotify(OvsdbClientIdl::Op op, + struct ovsdb_idl_row *row) { +} + +KSyncEntry *VMInterfaceKSyncObject::Alloc(const KSyncEntry *key, uint32_t index) { + const VMInterfaceKSyncEntry *k_entry = + static_cast(key); + VMInterfaceKSyncEntry *entry = new VMInterfaceKSyncEntry(this, k_entry); + return entry; +} + +KSyncEntry *VMInterfaceKSyncObject::DBToKSyncEntry(const DBEntry* db_entry) { + const VmInterface *entry = static_cast(db_entry); + VMInterfaceKSyncEntry *key = new VMInterfaceKSyncEntry(this, entry); + return static_cast(key); +} + +OvsdbDBEntry *VMInterfaceKSyncObject::AllocOvsEntry(struct ovsdb_idl_row *row) { + return NULL; +} + +KSyncDBObject::DBFilterResp VMInterfaceKSyncObject::DBEntryFilter( + const DBEntry *entry) { + const Interface *intf = static_cast(entry); + // only accept vm interfaces + if (intf->type() != Interface::VM_INTERFACE) { + return DBFilterIgnore; + } + return DBFilterAccept; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h new file mode 100644 index 00000000000..267720ef299 --- /dev/null +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VM_INTERFACE_KSYNC_H_ +#define SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VM_INTERFACE_KSYNC_H_ + +#include +#include + +class VmInterface; + +namespace OVSDB { +class VMInterfaceKSyncObject : public OvsdbDBObject { +public: + VMInterfaceKSyncObject(OvsdbClientIdl *idl, DBTable *table); + virtual ~VMInterfaceKSyncObject(); + + void OvsdbNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row*); + KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); + KSyncEntry *DBToKSyncEntry(const DBEntry*); + OvsdbDBEntry* AllocOvsEntry(struct ovsdb_idl_row*); + DBFilterResp DBEntryFilter(const DBEntry *entry); + +private: + DISALLOW_COPY_AND_ASSIGN(VMInterfaceKSyncObject); +}; + +class VMInterfaceKSyncEntry : public OvsdbDBEntry { +public: + VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + const VMInterfaceKSyncEntry *key); + VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + const VmInterface *entry); + VMInterfaceKSyncEntry(VMInterfaceKSyncObject *table, + boost::uuids::uuid uuid); + + bool IsDataResolved() {return true;}; + void AddMsg(struct ovsdb_idl_txn *); + void ChangeMsg(struct ovsdb_idl_txn *); + void DeleteMsg(struct ovsdb_idl_txn *); + bool Sync(DBEntry*); + bool IsLess(const KSyncEntry&) const; + std::string ToString() const {return "VM Interface Ksync";} + KSyncEntry* UnresolvedReference(); + +private: + friend class VMInterfaceKSyncObject; + boost::uuids::uuid uuid_; + std::string vn_name_; + DISALLOW_COPY_AND_ASSIGN(VMInterfaceKSyncEntry); +}; +}; + +#endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_VM_INTERFACE_KSYNC_H_ + From 2c810fab10a8ade6dceb75643227a7507b1a9f6a Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sat, 8 Nov 2014 09:34:49 +0530 Subject: [PATCH 183/218] Fix UT for noarp and point-to-point flag on eth interface --- src/vnsw/agent/oper/inet_interface.cc | 10 +- src/vnsw/agent/oper/interface.cc | 5 +- src/vnsw/agent/oper/physical_interface.h | 2 +- .../agent/oper/test/test_inet_interface.cc | 148 +++++++++++++----- 4 files changed, 123 insertions(+), 42 deletions(-) diff --git a/src/vnsw/agent/oper/inet_interface.cc b/src/vnsw/agent/oper/inet_interface.cc index b85ac49d8bb..7cead1ae1e7 100644 --- a/src/vnsw/agent/oper/inet_interface.cc +++ b/src/vnsw/agent/oper/inet_interface.cc @@ -153,7 +153,8 @@ static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, if (xconnect) { const PhysicalInterface *physical_intf = static_cast(xconnect); - if (physical_intf->no_arp()) { + if (physical_intf->no_arp() || + (physical_intf->encap_type() == PhysicalInterface::RAW_IP)) { table->AddInterfaceRouteReq(agent, agent->local_peer(), vrf->GetName(), Ip4Address(0), 0, xconnect, vn_name); @@ -186,8 +187,11 @@ static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, const PhysicalInterface *physical_intf = static_cast(xconnect); - if (physical_intf && physical_intf->no_arp()) { - return; + if (physical_intf) { + if (physical_intf->no_arp()) + return; + if (physical_intf->encap_type() != PhysicalInterface::ETHERNET) + return; } table->AddVHostSubnetRecvRoute(agent->local_peer(), vrf->GetName(), diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 90396b96be2..583534923d4 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -499,8 +499,9 @@ void PhysicalInterface::PostAdd() { close(fd); } -void PhysicalInterface::Delete() { - InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); +bool PhysicalInterface::Delete(const DBRequest *req) { + InterfaceNH::DeletePhysicalInterfaceNh(name_); + return true; } InterfaceKey *PhysicalInterfaceKey::Clone() const { diff --git a/src/vnsw/agent/oper/physical_interface.h b/src/vnsw/agent/oper/physical_interface.h index 4df8fa1785e..63f102b2961 100644 --- a/src/vnsw/agent/oper/physical_interface.h +++ b/src/vnsw/agent/oper/physical_interface.h @@ -31,7 +31,7 @@ class PhysicalInterface : public Interface { std::string ToString() const { return "ETH <" + name() + ">"; } KeyPtr GetDBRequestKey() const; virtual void Add(); - virtual void Delete(); + virtual bool Delete(const DBRequest *req); void PostAdd(); SubType subtype() const { return subtype_; } diff --git a/src/vnsw/agent/oper/test/test_inet_interface.cc b/src/vnsw/agent/oper/test/test_inet_interface.cc index 931e7412820..cb6ad8be9b1 100644 --- a/src/vnsw/agent/oper/test/test_inet_interface.cc +++ b/src/vnsw/agent/oper/test/test_inet_interface.cc @@ -284,7 +284,7 @@ TEST_F(InetInterfaceTest, ll_basic_1) { client->WaitForIdle(); } -static void DelInetConfig(Agent *agent, const Ip4Address &addr, +static void InetTestCleanup(Agent *agent, const Ip4Address &addr, const Ip4Address &gw, uint8_t plen) { InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); @@ -299,34 +299,46 @@ static void DelInetConfig(Agent *agent, const Ip4Address &addr, client->WaitForIdle(); } -static void AddInetRoutes(Agent *agent) { - AgentParam *agent_param = client->param(); - AgentRouteTable *table = agent->fabric_inet4_unicast_table(); - InetInterface::CreateReq(agent->interface_table(), agent_param->vhost_name(), - InetInterface::VHOST, agent->fabric_vrf_name(), - agent_param->vhost_addr(), - agent_param->vhost_plen(), - agent_param->vhost_gw(), - agent_param->eth_port(), - agent->fabric_vrf_name()); - WAIT_FOR(1000, 1000, - (RouteGet(agent->fabric_vrf_name(), agent_param->vhost_addr(), - agent_param->vhost_plen()) != NULL)); +static void RestoreInetConfig(Agent *agent) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + AgentParam *param = client->param(); + table->AddGatewayRouteReq(agent->local_peer(), agent->fabric_vrf_name(), + Ip4Address(0), 0, param->vhost_gw(), + agent->fabric_vrf_name(), + MplsTable::kInvalidLabel, SecurityGroupList()); client->WaitForIdle(); } +static void DelInetConfig(Agent *agent) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + Ip4Address(0), 0, NULL); +} + +static bool RouteValidate(Agent *agent, const Ip4Address &ip, uint8_t plen, + NextHop::Type nh_type) { + const InetUnicastRouteEntry *rt = NULL; + const NextHop *nh = NULL; + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent->fabric_vrf_name(), ip, plen)) != NULL)); + if (rt == NULL) + return false; + + nh = rt->GetActiveNextHop(); + return (nh->GetType() == nh_type); +} + TEST_F(InetInterfaceTest, physical_eth_encap_1) { const NextHop *nh = NULL; const InetUnicastRouteEntry *rt = NULL; AgentParam *param = client->param(); - - // Cleanup routes added by old inet-interface - DelInetConfig(agent_, param->vhost_addr(), param->vhost_gw(), - param->vhost_plen()); + DelInetConfig(agent_); Ip4Address ip = Ip4Address::from_string("10.10.10.10"); Ip4Address gw = Ip4Address::from_string("10.10.10.1"); Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; PhysicalInterface::CreateReq(interface_table_, "phy-1", agent_->fabric_vrf_name(), @@ -335,33 +347,97 @@ TEST_F(InetInterfaceTest, physical_eth_encap_1) { client->WaitForIdle(); InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, - agent_->fabric_vrf_name(), ip, 24, gw, "phy-1", + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", "TEST"); client->WaitForIdle(); - WAIT_FOR(1000, 1000, - ((rt = RouteGet(agent_->fabric_vrf_name(), ip, 32)) != NULL)); - if (rt != NULL) { - nh = rt->GetActiveNextHop(); - EXPECT_TRUE(nh->GetType() == NextHop::RECEIVE); - } + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + EXPECT_TRUE(RouteValidate(agent_, net, plen, NextHop::RESOLVE)); - WAIT_FOR(1000, 1000, - ((rt = RouteGet(agent_->fabric_vrf_name(), net, 24)) != NULL)); - if (rt != NULL) { - nh = rt->GetActiveNextHop(); - EXPECT_TRUE(nh->GetType() == NextHop::RESOLVE); - } + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); + + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_raw_ip_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + DelInetConfig(agent_); + + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; + + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::RAW_IP, false); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + // Subnet route not added when l2-encap is raw-ip + EXPECT_FALSE(RouteFind(agent_->fabric_vrf_name().c_str(), net, plen)); + EXPECT_TRUE(RouteValidate(agent_, Ip4Address(0), 0, NextHop::INTERFACE)); + + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); + + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_no_arp_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + DelInetConfig(agent_); - DelInetConfig(agent_, Ip4Address::from_string("10.10.10.10"), - Ip4Address::from_string("10.10.10.1"), 24); + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; - DelInterface(this, "vhost-1", agent_->fabric_vrf_name().c_str(), - "10.10.10.1"); + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, true); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + // Subnet route not added when l2-encap is raw-ip + EXPECT_FALSE(RouteFind(agent_->fabric_vrf_name().c_str(), net, plen)); + EXPECT_TRUE(RouteValidate(agent_, Ip4Address(0), 0, NextHop::INTERFACE)); + + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); PhysicalInterface::DeleteReq(interface_table_, "phy-1"); InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); - AddInetRoutes(agent_); + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); client->WaitForIdle(); } From 2e5fbd7c55a196c36525ef2dfc229eaa7dad2be8 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Sat, 8 Nov 2014 21:05:39 +0530 Subject: [PATCH 184/218] Fix unit test case. Dont add interface NH in subnet route. --- src/vnsw/agent/oper/agent_path.cc | 2 +- src/vnsw/agent/oper/multicast.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index 3e691aa7bd6..bc6d240ee67 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -90,7 +90,7 @@ bool AgentPath::ChangeNH(Agent *agent, NextHop *nh) { ret = true; } - if ((peer_->GetType() == Peer::MULTICAST_PEER) && + if (peer_ && (peer_->GetType() == Peer::MULTICAST_PEER) && (label_ != MplsTable::kInvalidLabel)) { MplsLabelKey key(MplsLabel::MCAST_NH, label_); MplsLabel *mpls = static_cast(agent->mpls_table()-> diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index 5ed0f8a423d..85e4eb2f534 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -85,9 +85,11 @@ void MulticastHandler::AddL2BroadcastRoute(MulticastGroupObject *obj, route_tunnel_bmap, Composite::L2INTERFACE, component_nh_key_list); + /* RebakeSubnetRoute(agent_->local_vm_peer(), vrf_name, label, vxlan_id, vn_name, false, component_nh_key_list, Composite::L2INTERFACE); + */ } /* From 6f7565e22f8ad284c8692256d8a27b2f49fadf9e Mon Sep 17 00:00:00 2001 From: Ashok Singh Date: Wed, 29 Oct 2014 10:15:57 -0700 Subject: [PATCH 185/218] Initial VCPE changes --- src/ifmap/ifmap_graph_walker.cc | 3 + src/vnsw/agent/cfg/cfg_init.cc | 9 + src/vnsw/agent/cfg/cfg_init.h | 5 + src/vnsw/agent/controller/controller_peer.cc | 20 ++ .../agent/controller/controller_route_path.cc | 81 ++++- .../agent/controller/controller_route_path.h | 28 +- src/vnsw/agent/init/agent_init.cc | 1 - src/vnsw/agent/ksync/interface_ksync.cc | 24 +- src/vnsw/agent/ksync/nexthop_ksync.cc | 12 +- src/vnsw/agent/oper/agent.sandesh | 2 + src/vnsw/agent/oper/agent_path.cc | 51 ++- src/vnsw/agent/oper/agent_path.h | 63 +++- src/vnsw/agent/oper/agent_route.cc | 6 +- src/vnsw/agent/oper/agent_route.h | 3 +- src/vnsw/agent/oper/global_vrouter.cc | 6 +- src/vnsw/agent/oper/inet_interface.cc | 11 +- src/vnsw/agent/oper/inet_unicast_route.cc | 148 ++++++--- src/vnsw/agent/oper/inet_unicast_route.h | 48 ++- src/vnsw/agent/oper/interface.cc | 6 + src/vnsw/agent/oper/mpls.cc | 24 +- src/vnsw/agent/oper/mpls.h | 5 + src/vnsw/agent/oper/nexthop.cc | 70 +++- src/vnsw/agent/oper/nexthop.h | 37 ++- src/vnsw/agent/oper/test/test_intf.cc | 94 ++++++ src/vnsw/agent/oper/vm_interface.cc | 226 +++++++++++-- src/vnsw/agent/oper/vm_interface.h | 30 +- src/vnsw/agent/oper/vn.cc | 16 +- src/vnsw/agent/oper/vn.h | 7 +- .../physical_devices/tables/physical_port.cc | 9 + src/vnsw/agent/pkt/pkt_flow_info.cc | 39 ++- src/vnsw/agent/pkt/pkt_handler.cc | 1 - src/vnsw/agent/services/arp_entry.cc | 149 +++++++-- src/vnsw/agent/services/arp_entry.h | 10 +- src/vnsw/agent/services/arp_handler.cc | 54 +++- src/vnsw/agent/services/arp_proto.cc | 195 ++++++++++-- src/vnsw/agent/services/arp_proto.h | 51 ++- src/vnsw/agent/services/services.sandesh | 15 + src/vnsw/agent/services/services_sandesh.cc | 35 ++ src/vnsw/agent/services/services_sandesh.h | 3 + src/vnsw/agent/services/test/arp_test.cc | 298 +++++++++++++++++- .../agent/test/test_agent_route_walker.cc | 6 +- src/vnsw/agent/test/test_cmn_util.h | 1 + src/vnsw/agent/test/test_l2route.cc | 5 +- src/vnsw/agent/test/test_nh.cc | 33 +- src/vnsw/agent/test/test_route.cc | 10 +- src/vnsw/agent/test/test_tunnel_encap.cc | 6 +- src/vnsw/agent/test/test_util.cc | 17 +- 47 files changed, 1704 insertions(+), 269 deletions(-) diff --git a/src/ifmap/ifmap_graph_walker.cc b/src/ifmap/ifmap_graph_walker.cc index cf3fb414790..5c80ce68bc2 100644 --- a/src/ifmap/ifmap_graph_walker.cc +++ b/src/ifmap/ifmap_graph_walker.cc @@ -244,6 +244,7 @@ void IFMapGraphWalker::AddNodesToWhitelist() { traversal_white_list_->include_vertex.insert("loadbalancer-pool"); traversal_white_list_->include_vertex.insert("loadbalancer-member"); traversal_white_list_->include_vertex.insert("loadbalancer-healthmonitor"); + traversal_white_list_->include_vertex.insert("subnet"); } void IFMapGraphWalker::AddLinksToWhitelist() { @@ -321,6 +322,8 @@ void IFMapGraphWalker::AddLinksToWhitelist() { "source=loadbalancer-pool,target=virtual-ip"); traversal_white_list_->include_edge.insert( "source=loadbalancer-pool,target=loadbalancer-member"); + traversal_white_list_->include_edge.insert( + "source=virtual-machine-interface,target=subnet"); // Manually add required links not picked by the // IFMapGraphTraversalFilterCalculator diff --git a/src/vnsw/agent/cfg/cfg_init.cc b/src/vnsw/agent/cfg/cfg_init.cc index f87dde7be53..f4f8be2c796 100644 --- a/src/vnsw/agent/cfg/cfg_init.cc +++ b/src/vnsw/agent/cfg/cfg_init.cc @@ -153,6 +153,10 @@ void AgentConfig::RegisterDBClients(DB *db) { boost::bind(&GlobalVrouter::GlobalVrouterConfig, agent_->oper_db()->global_vrouter(), _1), -1); + cfg_listener_->Register + ("subnet", boost::bind(&VmInterface::SubnetSync, + agent_->interface_table(), _1), -1); + cfg_vm_interface_table_ = (static_cast (IFMapTable::FindTable(agent_->db(), "virtual-machine-interface"))); assert(cfg_vm_interface_table_); @@ -208,6 +212,11 @@ void AgentConfig::RegisterDBClients(DB *db) { "interface-route-table"))); assert(cfg_route_table_); + cfg_subnet_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "subnet"))); + assert(cfg_route_table_); + cfg_interface_client_->Init(); } diff --git a/src/vnsw/agent/cfg/cfg_init.h b/src/vnsw/agent/cfg/cfg_init.h index c56d0cecbab..598de26c59c 100644 --- a/src/vnsw/agent/cfg/cfg_init.h +++ b/src/vnsw/agent/cfg/cfg_init.h @@ -57,6 +57,10 @@ class AgentConfig { return cfg_service_template_table_; } + IFMapAgentTable *cfg_subnet_table() const { + return cfg_subnet_table_; + } + Agent *agent() const { return agent_; } CfgFilter *cfg_filter() const { return cfg_filter_.get(); } CfgListener *cfg_listener() const { return cfg_listener_.get(); } @@ -108,6 +112,7 @@ class AgentConfig { IFMapAgentTable *cfg_vm_port_vrf_table_; IFMapAgentTable *cfg_route_table_; IFMapAgentTable *cfg_service_template_table_; + IFMapAgentTable *cfg_subnet_table_; DISALLOW_COPY_AND_ASSIGN(AgentConfig); }; diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index d6d49a30477..44828a6a7e3 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -879,6 +879,26 @@ void AgentXmppChannel::AddRemoteRoute(string vrf_name, IpAddress prefix_addr, AddEcmpRoute(vrf_name, prefix_addr.to_v4(), prefix_len, item); break; } + case NextHop::VRF: { + //In case of TOR/vCPE with a logical interface vlan1, + //example subnet 1.1.1.0/24 may be reachable on logical + //interface vlan1. Path added by local vm peer would point to + //resolve NH, so that if any path hits this route, ARP resolution + //can begin, and the label exported for this route would point to + //table nexthop. + //Hence existing logic of picking up nexthop from mpls label to + //nexthop, will not work. We have added a special path where we + //pick nexthop from local vm path, instead of BGP + BgpPeer *bgp_peer = bgp_peer_id(); + ClonedLocalPath *data = + new ClonedLocalPath(unicast_sequence_number(), this, + label, item->entry.virtual_network, + item->entry.security_group_list.security_group); + rt_table->AddClonedLocalPathReq(bgp_peer, vrf_name, + prefix_addr.to_v4(), + prefix_len, data); + break; + } default: CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name, diff --git a/src/vnsw/agent/controller/controller_route_path.cc b/src/vnsw/agent/controller/controller_route_path.cc index ebdf6b31ef9..040abbf5004 100644 --- a/src/vnsw/agent/controller/controller_route_path.cc +++ b/src/vnsw/agent/controller/controller_route_path.cc @@ -61,7 +61,8 @@ bool ControllerEcmpRoute::IsPeerValid() const { return CheckPeerValidity(channel(), sequence_number()); } -bool ControllerEcmpRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool ControllerEcmpRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { CompositeNHKey *comp_key = static_cast(nh_req_.key.get()); //Reorder the component NH list, and add a reference to local composite mpls //label if any @@ -100,7 +101,8 @@ bool ControllerVmRoute::IsPeerValid() const { return CheckPeerValidity(channel(), sequence_number()); } -bool ControllerVmRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool ControllerVmRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; SecurityGroupList path_sg_list; @@ -220,3 +222,78 @@ ControllerInetInterfaceRoute::ControllerInetInterfaceRoute(const InetInterfaceKe bool ControllerInetInterfaceRoute::IsPeerValid() const { return CheckPeerValidity(channel_, sequence_number_); } + +bool ClonedLocalPath::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { + bool ret = false; + const AgentPath *local_path = rt->FindLocalVmPortPath(); + + path->ChangeNH(agent, NULL); + if (!local_path) { + MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(mpls_label_); + if (!mpls) { + return false; + } + + //Do a route lookup in native VRF + assert(mpls->nexthop()->GetType() == NextHop::VRF); + const VrfNH *vrf_nh = static_cast(mpls->nexthop()); + const InetUnicastRouteEntry *uc_rt = + static_cast(rt); + const AgentRoute *rt = vrf_nh->GetVrf()->GetUcRoute(uc_rt->addr()); + if (rt == NULL) { + return false; + } + local_path = rt->FindLocalVmPortPath(); + if (!local_path) { + return false; + } + } + + if (path->dest_vn_name() != vn_) { + path->set_dest_vn_name(vn_); + ret = true; + } + path->set_unresolved(false); + + if (path->sg_list() != sg_list_) { + path->set_sg_list(sg_list_); + ret = true; + } + + path->set_tunnel_bmap(local_path->tunnel_bmap()); + TunnelType::Type new_tunnel_type = + TunnelType::ComputeType(path->tunnel_bmap()); + if (new_tunnel_type == TunnelType::VXLAN && + local_path->vxlan_id() == VxLanTable::kInvalidvxlan_id) { + new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType()); + } + + if (path->tunnel_type() != new_tunnel_type) { + path->set_tunnel_type(new_tunnel_type); + ret = true; + } + + // If policy force-enabled in request, enable policy + path->set_force_policy(local_path->force_policy()); + + if (path->label() != local_path->label()) { + path->set_label(local_path->label()); + ret = true; + } + + if (path->vxlan_id() != local_path->vxlan_id()) { + path->set_vxlan_id(local_path->vxlan_id()); + ret = true; + } + + NextHop *nh = const_cast(local_path->nexthop(agent)); + if (path->ChangeNH(agent, nh) == true) { + ret = true; + } + return ret; +} + +bool ClonedLocalPath::IsPeerValid() const { + return CheckPeerValidity(channel_, sequence_number_); +} diff --git a/src/vnsw/agent/controller/controller_route_path.h b/src/vnsw/agent/controller/controller_route_path.h index 893fa20146a..8ff90a9ff38 100644 --- a/src/vnsw/agent/controller/controller_route_path.h +++ b/src/vnsw/agent/controller/controller_route_path.h @@ -85,7 +85,8 @@ class ControllerVmRoute : public ControllerPeerPath { ControllerVmRoute(const Peer *peer) : ControllerPeerPath(peer) { } virtual ~ControllerVmRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual string ToString() const {return "remote VM";} virtual bool IsPeerValid() const; const SecurityGroupList &sg_list() const {return sg_list_;} @@ -127,7 +128,8 @@ class ControllerEcmpRoute : public ControllerPeerPath { {nh_req_.Swap(&nh_req);} virtual ~ControllerEcmpRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *); virtual string ToString() const {return "inet4 ecmp";} virtual bool IsPeerValid() const; @@ -209,4 +211,26 @@ class ControllerVlanNhRoute : public VlanNhRoute { DISALLOW_COPY_AND_ASSIGN(ControllerVlanNhRoute); }; +class ClonedLocalPath : public AgentRouteData { +public: + ClonedLocalPath(uint64_t seq, const AgentXmppChannel *channel, + uint32_t label, const std::string &vn, + const SecurityGroupList &sg_list): + AgentRouteData(false), sequence_number_(seq), + channel_(channel), mpls_label_(label), vn_(vn), sg_list_(sg_list) {} + virtual ~ClonedLocalPath() {} + virtual bool IsPeerValid() const; + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); + virtual std::string ToString() const { + return "Nexthop cloned from local path"; + } +private: + uint64_t sequence_number_; + const AgentXmppChannel *channel_; + uint32_t mpls_label_; + const std::string vn_; + const SecurityGroupList sg_list_; + DISALLOW_COPY_AND_ASSIGN(ClonedLocalPath); +}; #endif //controller_route_path_hpp diff --git a/src/vnsw/agent/init/agent_init.cc b/src/vnsw/agent/init/agent_init.cc index 839b58c1c28..a7f6ab472e4 100644 --- a/src/vnsw/agent/init/agent_init.cc +++ b/src/vnsw/agent/init/agent_init.cc @@ -229,7 +229,6 @@ void AgentInit::CreateVrfBase() { void AgentInit::CreateNextHopsBase() { DiscardNH::Create(); - ResolveNH::Create(); DiscardNHKey key; NextHop *nh = static_cast diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 3b61000abcc..1b677dd3488 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -352,9 +352,6 @@ KSyncEntry *InterfaceKSyncEntry::UnresolvedReference() { return NULL; } - if (rx_vlan_id_ == VmInterface::kInvalidVlanId) - return NULL; - if (parent_.get() && !parent_->IsResolved()) { return parent_.get(); } @@ -396,18 +393,25 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { flags |= VIF_FLAG_L2_ENABLED; } MacAddress mac; - if (rx_vlan_id_ == VmInterface::kInvalidVlanId) { - mac = ksync_obj_->ksync()->agent()->vrrp_mac(); - encoder.set_vifr_type(VIF_TYPE_VIRTUAL); - } else { + if (parent_.get() != NULL) { encoder.set_vifr_type(VIF_TYPE_VIRTUAL_VLAN); - encoder.set_vifr_vlan_id(rx_vlan_id_); - encoder.set_vifr_ovlan_id(tx_vlan_id_); + if (rx_vlan_id_ != VmInterface::kInvalidVlanId) { + encoder.set_vifr_vlan_id(rx_vlan_id_); + } else { + encoder.set_vifr_vlan_id(0); + } + if (tx_vlan_id_ != VmInterface::kInvalidVlanId) { + encoder.set_vifr_ovlan_id(tx_vlan_id_); + } else { + encoder.set_vifr_ovlan_id(0); + } InterfaceKSyncEntry *parent = (static_cast (parent_.get())); encoder.set_vifr_parent_vif_idx(parent->interface_id()); mac = parent->mac(); - + } else { + mac = ksync_obj_->ksync()->agent()->vrrp_mac(); + encoder.set_vifr_type(VIF_TYPE_VIRTUAL); } std::vector intf_mac((int8_t *)mac, (int8_t *)mac + mac.size()); diff --git a/src/vnsw/agent/ksync/nexthop_ksync.cc b/src/vnsw/agent/ksync/nexthop_ksync.cc index f82b1524904..c04009083eb 100644 --- a/src/vnsw/agent/ksync/nexthop_ksync.cc +++ b/src/vnsw/agent/ksync/nexthop_ksync.cc @@ -106,6 +106,12 @@ NHKSyncEntry::NHKSyncEntry(NHKSyncObject *obj, const NextHop *nh) : } case NextHop::RESOLVE: { + InterfaceKSyncObject *interface_object = + ksync_obj_->ksync()->interface_ksync_obj(); + const ResolveNH *rsl_nh = static_cast(nh); + InterfaceKSyncEntry if_ksync(interface_object, rsl_nh->interface()); + interface_ = interface_object->GetReference(&if_ksync); + vrf_id_ = rsl_nh->interface()->vrf_id(); break; } @@ -185,10 +191,11 @@ bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const { return type_ < entry.type_; } - if (type_ == NextHop::DISCARD || type_ == NextHop::RESOLVE) { + if (type_ == NextHop::DISCARD) { return false; } + if (policy_ != entry.policy_) { return policy_ < entry.policy_; } @@ -214,10 +221,11 @@ bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const { return interface() < entry.interface(); } - if (type_ == NextHop::RECEIVE) { + if (type_ == NextHop::RECEIVE || type_ == NextHop::RESOLVE) { return interface() < entry.interface(); } + if (type_ == NextHop::TUNNEL) { if (vrf_id_ != entry.vrf_id_) { return vrf_id_ < entry.vrf_id_; diff --git a/src/vnsw/agent/oper/agent.sandesh b/src/vnsw/agent/oper/agent.sandesh index ee6f76e0419..5b4b25a08e1 100644 --- a/src/vnsw/agent/oper/agent.sandesh +++ b/src/vnsw/agent/oper/agent.sandesh @@ -69,6 +69,7 @@ struct ItfSandeshData { 37: i16 tx_vlan_id; 38: i16 rx_vlan_id; 39: string parent_interface; + 40: optional string subnet; } struct VnIpamData { @@ -97,6 +98,7 @@ struct VnSandeshData { 9: bool layer2_forwarding; 10: bool ipv4_forwarding; 11: bool admin_state; + 12: i32 table_label; } struct SgSandeshData { diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index bc6d240ee67..cc21c74f82d 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -261,7 +261,11 @@ bool AgentPath::Sync(AgentRoute *sync_route) { if (rt == NULL || rt->plen() == 0) { unresolved = true; } else if (rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE) { - table->AddArpReq(vrf_name_, gw_ip_); + const ResolveNH *nh = + static_cast(rt->GetActiveNextHop()); + table->AddArpReq(vrf_name_, gw_ip_, nh->interface()->vrf()->GetName(), + nh->interface(), nh->PolicyEnabled(), dest_vn_name_, + sg_list_); unresolved = true; } else { unresolved = false; @@ -295,7 +299,8 @@ bool AgentPath::IsLess(const AgentPath &r_path) const { return peer()->IsLess(r_path.peer()); } -bool HostRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool HostRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; InterfaceNHKey key(intf_.Clone(), false, InterfaceNHFlags::INET4); @@ -317,7 +322,8 @@ bool HostRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool InetInterfaceRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool InetInterfaceRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; InterfaceNHKey key(intf_.Clone(), false, InterfaceNHFlags::INET4); @@ -346,7 +352,8 @@ bool InetInterfaceRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool DropRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool DropRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; if (path->dest_vn_name() != vn_) { @@ -363,7 +370,8 @@ bool DropRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool LocalVmRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool LocalVmRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; SecurityGroupList path_sg_list; @@ -472,7 +480,8 @@ bool LocalVmRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool VlanNhRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool VlanNhRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; SecurityGroupList path_sg_list; @@ -523,24 +532,38 @@ bool VlanNhRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool ResolveRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool ResolveRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; - ResolveNHKey key; + ResolveNHKey key(intf_key_.get(), policy_); nh = static_cast(agent->nexthop_table()->FindActiveEntry(&key)); path->set_unresolved(false); - if (path->dest_vn_name() != agent->fabric_vn_name()) { - path->set_dest_vn_name(agent->fabric_vn_name()); + + if (path->dest_vn_name() != dest_vn_name_) { + path->set_dest_vn_name(dest_vn_name_); + ret = true; + } + + if (path->label() != label_) { + path->set_label(label_); + ret = true; + } + + if (path->sg_list() != path_sg_list_) { + path->set_sg_list(path_sg_list_); ret = true; } + if (path->ChangeNH(agent, nh) == true) ret = true; return ret; } -bool ReceiveRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool ReceiveRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; NextHop *nh = NULL; @@ -570,7 +593,8 @@ bool ReceiveRoute::AddChangePath(Agent *agent, AgentPath *path) { return ret; } -bool MulticastRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool MulticastRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; bool is_subnet_discard = false; NextHop *nh = NULL; @@ -634,7 +658,8 @@ bool MulticastRoute::CopyPathParameters(Agent *agent, return true; } -bool PathPreferenceData::AddChangePath(Agent *agent, AgentPath *path) { +bool PathPreferenceData::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; //ECMP flag will not be changed by path preference module, //hence retain value in path diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index e0868c1da34..54cd1edd949 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -91,7 +91,7 @@ struct PathPreferenceData : public AgentRouteData { virtual std::string ToString() const { return ""; } - virtual bool AddChangePath(Agent*, AgentPath*); + virtual bool AddChangePath(Agent*, AgentPath*, const AgentRoute*); PathPreference path_preference_; }; @@ -133,7 +133,7 @@ class AgentPath : public Path { void set_vrf_name(const std::string &vrf_name) {vrf_name_ = vrf_name;} void set_tunnel_bmap(TunnelType::TypeBmap bmap) {tunnel_bmap_ = bmap;} void set_tunnel_type(TunnelType::Type type) {tunnel_type_ = type;} - void set_sg_list(SecurityGroupList &sg) {sg_list_ = sg;} + void set_sg_list(const SecurityGroupList &sg) {sg_list_ = sg;} void clear_sg_list() { sg_list_.clear(); } void set_server_ip(const Ip4Address &server_ip) {server_ip_ = server_ip;} void set_is_subnet_discard(bool discard) { @@ -230,11 +230,20 @@ class AgentPath : public Path { class ResolveRoute : public AgentRouteData { public: - ResolveRoute() : AgentRouteData(false) { } + ResolveRoute(const InterfaceKey *key, bool policy, const uint32_t label, + const string &vn_name, const SecurityGroupList &sg_list) : + AgentRouteData(false), intf_key_(key->Clone()), policy_(policy), + label_(label), dest_vn_name_(vn_name), path_sg_list_(sg_list) {} virtual ~ResolveRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "Resolve";} private: + boost::scoped_ptr intf_key_; + bool policy_; + uint32_t label_; + const std::string dest_vn_name_; + const SecurityGroupList path_sg_list_; DISALLOW_COPY_AND_ASSIGN(ResolveRoute); }; @@ -254,7 +263,8 @@ class LocalVmRoute : public AgentRouteData { virtual ~LocalVmRoute() { } void DisableProxyArp() {proxy_arp_ = false;} virtual std::string ToString() const {return "local VM";} - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); const SecurityGroupList &sg_list() const {return sg_list_;} void set_tunnel_bmap(TunnelType::TypeBmap bmap) {tunnel_bmap_ = bmap;} const PathPreference& path_preference() const { return path_preference_;} @@ -288,7 +298,8 @@ class InetInterfaceRoute : public AgentRouteData { tunnel_bmap_(tunnel_bmap), dest_vn_name_(dest_vn_name) { } virtual ~InetInterfaceRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "host";} private: @@ -307,7 +318,8 @@ class HostRoute : public AgentRouteData { } virtual ~HostRoute() { } void EnableProxyArp() {proxy_arp_ = true;} - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "host";} private: @@ -327,7 +339,8 @@ class VlanNhRoute : public AgentRouteData { path_preference_(path_preference), tunnel_bmap_(TunnelType::MplsType()) { } virtual ~VlanNhRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "vlannh";} private: @@ -351,7 +364,8 @@ class MulticastRoute : public AgentRouteData { composite_nh_req_.Swap(&nh_req); } virtual ~MulticastRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "multicast";} static bool CopyPathParameters(Agent *agent, AgentPath *path, @@ -392,7 +406,8 @@ class ReceiveRoute : public AgentRouteData { } virtual ~ReceiveRoute() { } void EnableProxyArp() {proxy_arp_ = true;} - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "receive";} private: @@ -409,32 +424,45 @@ class ReceiveRoute : public AgentRouteData { class Inet4UnicastArpRoute : public AgentRouteData { public: Inet4UnicastArpRoute(const std::string &vrf_name, - const Ip4Address &addr) : - AgentRouteData(false), vrf_name_(vrf_name), addr_(addr) { + const Ip4Address &addr, bool policy, + const std::string &vn, const SecurityGroupList &sg) : + AgentRouteData(false), vrf_name_(vrf_name), addr_(addr), + policy_(policy), vn_(vn), sg_list_(sg) { } virtual ~Inet4UnicastArpRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "arp";} private: std::string vrf_name_; Ip4Address addr_; + bool policy_; + std::string vn_; + SecurityGroupList sg_list_; DISALLOW_COPY_AND_ASSIGN(Inet4UnicastArpRoute); }; class Inet4UnicastGatewayRoute : public AgentRouteData { public: Inet4UnicastGatewayRoute(const Ip4Address &gw_ip, - const std::string &vrf_name) : - AgentRouteData(false), gw_ip_(gw_ip), vrf_name_(vrf_name) { + const std::string &vrf_name, + const std::string &vn_name, + uint32_t label, const SecurityGroupList &sg) : + AgentRouteData(false), gw_ip_(gw_ip), vrf_name_(vrf_name), + vn_name_(vn_name), mpls_label_(label), sg_list_(sg) { } virtual ~Inet4UnicastGatewayRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "gateway";} private: Ip4Address gw_ip_; std::string vrf_name_; + std::string vn_name_; + uint32_t mpls_label_; + const SecurityGroupList sg_list_; DISALLOW_COPY_AND_ASSIGN(Inet4UnicastGatewayRoute); }; @@ -443,7 +471,8 @@ class DropRoute : public AgentRouteData { DropRoute(const string &vn_name) : AgentRouteData(false), vn_(vn_name) { } virtual ~DropRoute() { } - virtual bool AddChangePath(Agent *agent, AgentPath *path); + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); virtual std::string ToString() const {return "drop";} private: std::string vn_; diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index 7aec1accb30..09a645c01fb 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -324,7 +324,7 @@ void AgentRouteTable::Input(DBTablePartition *part, DBClient *client, //wait for traffic flag for a path path = rt->FindPath(key->peer()); if (path) { - notify = data->AddChangePath(agent_, path); + notify = data->AddChangePath(agent_, path, rt); } } else { //Ignore RESYNC if received on non-existing @@ -369,7 +369,7 @@ void AgentRouteTable::Input(DBTablePartition *part, DBClient *client, if (path == NULL) { path = new AgentPath(key->peer(), rt); rt->InsertPath(path); - data->AddChangePath(agent_, path); + data->AddChangePath(agent_, path, rt); notify = true; RouteInfo rt_info; @@ -379,7 +379,7 @@ void AgentRouteTable::Input(DBTablePartition *part, DBClient *client, // Let path know of route change and update itself path->set_is_stale(false); bool ecmp = path->path_preference().ecmp(); - notify = data->AddChangePath(agent_, path); + notify = data->AddChangePath(agent_, path, rt); //If a path transition from ECMP to non ECMP //remote the path from ecmp peer if (ecmp && ecmp != path->path_preference().ecmp()) { diff --git a/src/vnsw/agent/oper/agent_route.h b/src/vnsw/agent/oper/agent_route.h index 19d4cf0cf2f..72b80b4f6fa 100644 --- a/src/vnsw/agent/oper/agent_route.h +++ b/src/vnsw/agent/oper/agent_route.h @@ -64,7 +64,8 @@ struct AgentRouteData : public AgentData { virtual ~AgentRouteData() { } virtual std::string ToString() const = 0; - virtual bool AddChangePath(Agent *agent, AgentPath *path) = 0; + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) = 0; virtual bool IsPeerValid() const {return true;} bool is_multicast() const {return is_multicast_;} diff --git a/src/vnsw/agent/oper/global_vrouter.cc b/src/vnsw/agent/oper/global_vrouter.cc index c1d9c870d5a..bdc6c13f8c4 100644 --- a/src/vnsw/agent/oper/global_vrouter.cc +++ b/src/vnsw/agent/oper/global_vrouter.cc @@ -243,9 +243,9 @@ void GlobalVrouter::LinkLocalRouteManager::AddArpRoute(const Ip4Address &srv) { return; } - InetUnicastAgentRouteTable::CheckAndAddArpReq(global_vrouter_->oper_db()-> - agent()->fabric_vrf_name(), - srv); + Agent *agent = global_vrouter_->oper_db()->agent(); + InetUnicastAgentRouteTable::CheckAndAddArpReq(agent->fabric_vrf_name(), + srv, agent->vhost_interface()); } // Walk thru all the VNs diff --git a/src/vnsw/agent/oper/inet_interface.cc b/src/vnsw/agent/oper/inet_interface.cc index 5fa9c67a152..9986c06fc12 100644 --- a/src/vnsw/agent/oper/inet_interface.cc +++ b/src/vnsw/agent/oper/inet_interface.cc @@ -150,7 +150,9 @@ static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, const VrfEntry *vrf, const Ip4Address &gw, const string &vn_name) { - table->AddGatewayRoute(vrf->GetName(), Ip4Address(0), 0, gw, vn_name); + table->AddGatewayRoute(agent->local_peer(), + vrf->GetName(), Ip4Address(0), 0, gw, vn_name, + MplsTable::kInvalidLabel, SecurityGroupList()); } static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, @@ -175,8 +177,11 @@ static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, GetIp4SubnetBroadcastAddress(addr, plen), 32, vn_name, false); - table->AddResolveRoute(vrf->GetName(), - Address::GetIp4SubnetAddress(addr, plen), plen); + InetInterfaceKey intf_key(interface); + table->AddResolveRoute(agent->local_peer(), vrf->GetName(), + Address::GetIp4SubnetAddress(addr, plen), plen, + intf_key, MplsTable::kInvalidLabel, false, vn_name, + SecurityGroupList()); } static void DeleteHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 04755b8846d..2e88ab94a9a 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include using namespace std; @@ -617,25 +618,33 @@ bool InetUnicastRouteEntry::is_multicast() const { // AgentRouteData virtual functions ///////////////////////////////////////////////////////////////////////////// -bool Inet4UnicastArpRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool Inet4UnicastArpRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { bool ret = false; - ArpNHKey key(vrf_name_, addr_); + ArpNHKey key(vrf_name_, addr_, policy_); NextHop *nh = static_cast(agent->nexthop_table()->FindActiveEntry(&key)); path->set_unresolved(false); - path->set_dest_vn_name(agent->fabric_vn_name()); - if (path->dest_vn_name() != agent->fabric_vn_name()) { + + if (path->dest_vn_name() != vn_) { + path->set_dest_vn_name(vn_); ret = true; } - ret = true; + + if (path->sg_list() != sg_list_) { + path->set_sg_list(sg_list_); + ret = true; + } + if (path->ChangeNH(agent, nh) == true) ret = true; return ret; -} +} -bool Inet4UnicastGatewayRoute::AddChangePath(Agent *agent, AgentPath *path) { +bool Inet4UnicastGatewayRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *agent_rt) { path->set_vrf_name(vrf_name_); InetUnicastAgentRouteTable *table = NULL; @@ -645,17 +654,32 @@ bool Inet4UnicastGatewayRoute::AddChangePath(Agent *agent, AgentPath *path) { if (rt == NULL || rt->plen() == 0) { path->set_unresolved(true); } else if (rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE) { + const ResolveNH *nh = + static_cast(rt->GetActiveNextHop()); path->set_unresolved(true); - InetUnicastAgentRouteTable::AddArpReq(vrf_name_, gw_ip_); + InetUnicastAgentRouteTable::AddArpReq(vrf_name_, gw_ip_, + nh->interface()->vrf()->GetName(), + nh->interface(), nh->PolicyEnabled(), + vn_name_, sg_list_); } else { path->set_unresolved(false); } + if (path->label() != mpls_label_) { + path->set_label(mpls_label_); + } + + SecurityGroupList path_sg_list; + path_sg_list = path->sg_list(); + if (path_sg_list != sg_list_) { + path->set_sg_list(sg_list_); + } + //Reset to new gateway route, no nexthop for indirect route path->set_gw_ip(gw_ip_); path->ResetDependantRoute(rt); - if (path->dest_vn_name() != agent->fabric_vn_name()) { - path->set_dest_vn_name(agent->fabric_vn_name()); + if (path->dest_vn_name() != vn_name_) { + path->set_dest_vn_name(vn_name_); } return true; @@ -920,6 +944,18 @@ InetUnicastAgentRouteTable::AddLocalVmRouteReq(const Peer *peer, AddLocalVmRouteReq(peer, vm_vrf, addr, plen, data); } +void +InetUnicastAgentRouteTable::AddClonedLocalPathReq(const Peer *peer, + const string &vm_vrf, + const IpAddress &addr, + uint8_t plen, + ClonedLocalPath *data) { + DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); + req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen)); + req.data.reset(data); + Inet4UnicastTableEnqueue(Agent::GetInstance(), &req); +} + // Create Route for a local VM // Assumes that Interface-NH for "VM Port" is already present void @@ -993,32 +1029,41 @@ InetUnicastAgentRouteTable::AddRemoteVmRouteReq(const Peer *peer, } void -InetUnicastAgentRouteTable::AddArpReq(const string &vrf_name, - const Ip4Address &ip) { +InetUnicastAgentRouteTable::AddArpReq(const string &route_vrf_name, + const Ip4Address &ip, + const string &nexthop_vrf_name, + const Interface *intf, bool policy, + const std::string &vn_name, + const SecurityGroupList &sg_list) { Agent *agent = Agent::GetInstance(); DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new ArpNHKey(vrf_name, ip)); - nh_req.data.reset(new ArpNHData()); + nh_req.key.reset(new ArpNHKey(route_vrf_name, ip, policy)); + nh_req.data.reset(new ArpNHData( + static_cast(intf->GetDBRequestKey().release()))); agent->nexthop_table()->Enqueue(&nh_req); DBRequest rt_req(DBRequest::DB_ENTRY_ADD_CHANGE); rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(), - vrf_name, ip, 32)); - rt_req.data.reset(new Inet4UnicastArpRoute(vrf_name, ip)); + route_vrf_name, ip, 32)); + rt_req.data.reset(new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy, + vn_name, sg_list)); Inet4UnicastTableEnqueue(agent, &rt_req); } void InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op, + const string &route_vrf_name, const Ip4Address &ip, const MacAddress &mac, - const string &vrf_name, + const string &nexthop_vrf_name, const Interface &intf, bool resolved, - const uint8_t plen) { + const uint8_t plen, + bool policy, const std::string &vn_name, + const SecurityGroupList &sg) { Agent *agent = Agent::GetInstance(); DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new ArpNHKey(vrf_name, ip)); + nh_req.key.reset(new ArpNHKey(nexthop_vrf_name, ip, policy)); ArpNHData *arp_data = new ArpNHData(mac, static_cast(intf.GetDBRequestKey().release()), resolved); @@ -1026,17 +1071,17 @@ InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op, DBRequest rt_req(op); InetUnicastRouteKey *rt_key = - new InetUnicastRouteKey(agent->local_peer(), vrf_name, ip, plen); + new InetUnicastRouteKey(agent->local_peer(), route_vrf_name, ip, plen); Inet4UnicastArpRoute *data = NULL; switch(op) { case DBRequest::DB_ENTRY_ADD_CHANGE: agent->nexthop_table()->Enqueue(&nh_req); - data = new Inet4UnicastArpRoute(vrf_name, ip); + data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy, vn_name, sg); break; case DBRequest::DB_ENTRY_DELETE: { - VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name); + VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(route_vrf_name); InetUnicastRouteEntry *rt = static_cast(vrf-> GetInet4UnicastRouteTable()->Find(rt_key)); @@ -1045,7 +1090,8 @@ InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op, // If no other route is dependent on this, remove the route; else ignore if (rt && rt->IsDependantRouteEmpty() && rt->IsTunnelNHListEmpty()) { - data = new Inet4UnicastArpRoute(vrf_name, ip); + data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy, + vn_name, sg); } else { rt_key->sub_op_ = AgentKey::RESYNC; rt_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; @@ -1064,7 +1110,8 @@ InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op, void InetUnicastAgentRouteTable::CheckAndAddArpReq(const string &vrf_name, - const Ip4Address &ip) { + const Ip4Address &ip, + const Interface *intf) { if (ip == Agent::GetInstance()->router_id() || !IsIp4SubnetMember(ip, Agent::GetInstance()->router_id(), @@ -1073,17 +1120,25 @@ InetUnicastAgentRouteTable::CheckAndAddArpReq(const string &vrf_name, // Currently, default GW Arp is added during init return; } - AddArpReq(vrf_name, ip); + //AddArpReq(vrf_name, ip, intf->vrf()->GetName(), intf); } -void InetUnicastAgentRouteTable::AddResolveRoute(const string &vrf_name, +void InetUnicastAgentRouteTable::AddResolveRoute(const Peer *peer, + const string &vrf_name, const Ip4Address &ip, - const uint8_t plen) { + const uint8_t plen, + const InterfaceKey &intf, + const uint32_t label, + bool policy, + const std::string &vn_name, + const SecurityGroupList + &sg_list) { Agent *agent = Agent::GetInstance(); + ResolveNH::Create(&intf, policy); DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); - req.key.reset(new InetUnicastRouteKey(agent->local_peer(), vrf_name, ip, + req.key.reset(new InetUnicastRouteKey(peer, vrf_name, ip, plen)); - req.data.reset(new ResolveRoute()); + req.data.reset(new ResolveRoute(&intf, policy, label, vn_name, sg_list)); Inet4UnicastTableEnqueue(agent, &req); } @@ -1186,34 +1241,47 @@ void InetUnicastAgentRouteTable::DelVHostSubnetRecvRoute(const string &vm_vrf, Address::GetIp4SubnetAddress(addr, plen), 32, NULL); } -static void AddGatewayRouteInternal(DBRequest *req, const string &vrf_name, +static void AddGatewayRouteInternal(const Peer *peer, + DBRequest *req, const string &vrf_name, const Ip4Address &dst_addr, uint8_t plen, const Ip4Address &gw_ip, - const string &vn_name) { + const string &vn_name, uint32_t label, + const SecurityGroupList &sg_list) { req->oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req->key.reset(new InetUnicastRouteKey(Agent::GetInstance()->local_peer(), - vrf_name, dst_addr, plen)); - req->data.reset(new Inet4UnicastGatewayRoute(gw_ip, vrf_name)); + req->key.reset(new InetUnicastRouteKey(peer, + vrf_name, dst_addr, plen)); + req->data.reset(new Inet4UnicastGatewayRoute(gw_ip, vrf_name, + vn_name, label, sg_list)); } -void InetUnicastAgentRouteTable::AddGatewayRoute(const string &vrf_name, +void InetUnicastAgentRouteTable::AddGatewayRoute(const Peer *peer, + const string &vrf_name, const Ip4Address &dst_addr, uint8_t plen, const Ip4Address &gw_ip, - const string &vn_name) { + const string &vn_name, + uint32_t label, + const SecurityGroupList + &sg_list) { DBRequest req; - AddGatewayRouteInternal(&req, vrf_name, dst_addr, plen, gw_ip, vn_name); + AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_ip, vn_name, + label, sg_list); Inet4UnicastTableProcess(Agent::GetInstance(), vrf_name, req); } void -InetUnicastAgentRouteTable::AddGatewayRouteReq(const string &vrf_name, +InetUnicastAgentRouteTable::AddGatewayRouteReq(const Peer *peer, + const string &vrf_name, const Ip4Address &dst_addr, uint8_t plen, const Ip4Address &gw_ip, - const string &vn_name) { + const string &vn_name, + uint32_t label, + const SecurityGroupList + &sg_list) { DBRequest req; - AddGatewayRouteInternal(&req, vrf_name, dst_addr, plen, gw_ip, vn_name); + AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_ip, + vn_name, label, sg_list); Inet4UnicastTableEnqueue(Agent::GetInstance(), &req); } diff --git a/src/vnsw/agent/oper/inet_unicast_route.h b/src/vnsw/agent/oper/inet_unicast_route.h index 1a7277a4561..ee057610805 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.h +++ b/src/vnsw/agent/oper/inet_unicast_route.h @@ -8,6 +8,7 @@ class VlanNhRoute; class LocalVmRoute; class InetInterfaceRoute; +class ClonedLocalPath; ////////////////////////////////////////////////////////////////// // UNICAST INET @@ -157,6 +158,11 @@ class InetUnicastAgentRouteTable : public AgentRouteTable { InetUnicastRouteEntry *FindRoute(const IpAddress &ip) { return FindLPM(ip); } + + const InetUnicastRouteEntry *GetNext(const InetUnicastRouteEntry *rt) { + return static_cast(tree_.FindNext(rt)); + } + static DBTableBase *CreateTable(DB *db, const std::string &name); static void ReEvaluatePaths(const string &vrf_name, const IpAddress &ip, uint8_t plen); @@ -215,17 +221,32 @@ class InetUnicastAgentRouteTable : public AgentRouteTable { InetUnicastRouteEntry *FindResolveRoute(const Ip4Address &ip); static InetUnicastRouteEntry *FindResolveRoute(const string &vrf_name, const Ip4Address &ip); - static void CheckAndAddArpReq(const string &vrf_name, const Ip4Address &ip); - static void AddArpReq(const string &vrf_name, const Ip4Address &ip); + static void CheckAndAddArpReq(const string &vrf_name, const Ip4Address &ip, + const Interface *intf); + static void AddArpReq(const string &route_vrf_name, + const Ip4Address &ip, + const string &nh_vrf_name, + const Interface *intf, + bool policy, const string &dest_vn_name, + const SecurityGroupList &sg_list); static void ArpRoute(DBRequest::DBOperation op, + const string &route_vrf_name, const Ip4Address &ip, const MacAddress &mac, - const string &vrf_name, + const string &nh_vrf_name, const Interface &intf, bool resolved, - const uint8_t plen); - static void AddResolveRoute(const string &vrf_name, const Ip4Address &ip, - const uint8_t plen); + const uint8_t plen, + bool policy, + const string &dest_vn_name, + const SecurityGroupList &sg_list); + static void AddResolveRoute(const Peer *peer, + const string &vrf_name, const Ip4Address &ip, + const uint8_t plen, + const InterfaceKey &intf_key, + const uint32_t label, bool policy, + const std::string &vn_name, + const SecurityGroupList &sg_list); void AddInetInterfaceRouteReq(const Peer *peer, const string &vm_vrf, const Ip4Address &addr, uint8_t plen, InetInterfaceRoute *data); @@ -251,17 +272,24 @@ class InetUnicastAgentRouteTable : public AgentRouteTable { static void AddDropRoute(const string &vm_vrf, const Ip4Address &addr, uint8_t plen, const string &vn_name); - static void AddGatewayRoute(const string &vrf_name, + static void AddGatewayRoute(const Peer *peer, + const string &vrf_name, const Ip4Address &dst_addr,uint8_t plen, const Ip4Address &gw_ip, - const std::string &vn_name); - static void AddGatewayRouteReq(const string &vrf_name, + const std::string &vn_name, uint32_t label, + const SecurityGroupList &sg_list); + static void AddGatewayRouteReq(const Peer *peer, + const string &vrf_name, const Ip4Address &dst_addr,uint8_t plen, const Ip4Address &gw_ip, - const std::string &vn_name); + const std::string &vn_name, uint32_t label, + const SecurityGroupList &sg_list); void AddSubnetRoute(const string &vm_vrf, const IpAddress &addr, uint8_t plen, const string &vn_name, uint32_t vxlan_id); + void AddClonedLocalPathReq(const Peer *peer, const string &vm_vrf, + const IpAddress &addr, + uint8_t plen, ClonedLocalPath *data); private: Agent::RouteTableType type_; diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index dadd6815498..0c1cee3d406 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -815,6 +815,12 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { if (vintf->parent()) { data.set_parent_interface(vintf->parent()->name()); } + if (vintf->subnet().to_ulong() != 0) { + std::ostringstream str; + str << vintf->subnet().to_string() << "/" + << (int)vintf->subnet_plen(); + data.set_subnet(str.str()); + } break; } case Interface::INET: diff --git a/src/vnsw/agent/oper/mpls.cc b/src/vnsw/agent/oper/mpls.cc index c54f5b20a4f..3d74c48a3f1 100644 --- a/src/vnsw/agent/oper/mpls.cc +++ b/src/vnsw/agent/oper/mpls.cc @@ -203,7 +203,29 @@ void MplsLabel::CreateEcmpLabel(uint32_t label, COMPOSITETYPE type, MplsTable::GetInstance()->Process(req); return; } - + +void MplsLabel::CreateTableLabel(uint32_t label, const std::string &vrf_name, + bool policy) { + DBRequest nh_req; + nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + VrfNHKey *vrf_nh_key = new VrfNHKey(vrf_name, false); + nh_req.key.reset(vrf_nh_key); + nh_req.data.reset(NULL); + Agent::GetInstance()->nexthop_table()->Process(nh_req); + + DBRequest req; + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + + MplsLabelKey *key = new MplsLabelKey(MplsLabel::VPORT_NH, label); + req.key.reset(key); + + MplsLabelData *data = new MplsLabelData(vrf_name, policy); + req.data.reset(data); + + MplsTable::GetInstance()->Process(req); + return; +} + void MplsLabel::DeleteMcastLabelReq(uint32_t src_label) { DBRequest req; req.oper = DBRequest::DB_ENTRY_DELETE; diff --git a/src/vnsw/agent/oper/mpls.h b/src/vnsw/agent/oper/mpls.h index 91989c53f1f..5b0188c6049 100644 --- a/src/vnsw/agent/oper/mpls.h +++ b/src/vnsw/agent/oper/mpls.h @@ -53,6 +53,8 @@ class MplsLabel : AgentRefCount, public AgentDBEntry { static void CreateEcmpLabel(uint32_t label, COMPOSITETYPE type, ComponentNHKeyList &component_nh_key_list, const std::string vrf_name); + static void CreateTableLabel(uint32_t label, const std::string &vrf_name, + bool policy); static void DeleteMcastLabelReq(uint32_t src_label); // Delete MPLS Label entry static void DeleteReq(uint32_t label); @@ -113,6 +115,9 @@ class MplsLabelData : public AgentData { component_nh_key_list, vrf_name)) { } + MplsLabelData(const std::string vrf_name, bool policy) : + AgentData(), nh_key(new VrfNHKey(vrf_name, policy)) { + } virtual ~MplsLabelData() { if (nh_key) { delete nh_key; diff --git a/src/vnsw/agent/oper/nexthop.cc b/src/vnsw/agent/oper/nexthop.cc index 938e929f69f..acca500f19e 100644 --- a/src/vnsw/agent/oper/nexthop.cc +++ b/src/vnsw/agent/oper/nexthop.cc @@ -305,10 +305,12 @@ void ArpNH::SetKey(const DBRequestKey *k) { bool ArpNH::Change(const DBRequest *req) { bool ret= false; + const ArpNHKey *key = static_cast(req->key.get()); const ArpNHData *data = static_cast(req->data.get()); - if (!data->valid_) { - return ret; + if (policy_ != key->policy_) { + policy_ = key->policy_; + ret = true; } if (valid_ != data->resolved_) { @@ -316,18 +318,22 @@ bool ArpNH::Change(const DBRequest *req) { ret = true; } - if (data->resolved_ != true) { - // If ARP is not resolved, interface and mac will be invalid - interface_ = NULL; - return ret; - } - - Interface *interface = NextHopTable::GetInstance()->FindInterface(*data->intf_key_.get()); + Interface *interface = NextHopTable::GetInstance()->FindInterface + (*data->intf_key_.get()); if (interface_.get() != interface) { interface_ = interface; ret = true; } + if (!data->valid_) { + return ret; + } + + if (data->resolved_ != true) { + // If ARP is not resolved mac will be invalid + return ret; + } + if (mac_.CompareTo(data->mac_) != 0) { mac_ = data->mac_; ret = true; @@ -341,7 +347,7 @@ const uint32_t ArpNH::vrf_id() const { } ArpNH::KeyPtr ArpNH::GetDBRequestKey() const { - NextHopKey *key = new ArpNHKey(vrf_->GetName(), ip_); + NextHopKey *key = new ArpNHKey(vrf_->GetName(), ip_, policy_); return DBEntryBase::KeyPtr(key); } @@ -718,7 +724,23 @@ bool TunnelNH::Change(const DBRequest *req) { //Trigger ARP resolution valid = false; rt_table->AddUnresolvedNH(this); - InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_); + const ResolveNH *nh = + static_cast(rt->GetActiveNextHop()); + SecurityGroupList sg_list; + std::string vn = ""; + if (nh->interface()->type() == Interface::VM_INTERFACE) { + const VmInterface *vm_intf = + static_cast(nh->interface()); + vm_intf->CopySgIdList(&sg_list); + if (vm_intf->vn()) { + vn = vm_intf->vn()->GetName(); + } + } + InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_, + nh->interface()->vrf()->GetName(), + nh->interface(), + nh->PolicyEnabled(), + vn, sg_list); rt = NULL; } else { valid = rt->GetActiveNextHop()->IsValid(); @@ -824,7 +846,23 @@ bool MirrorNH::Change(const DBRequest *req) { //Trigger ARP resolution valid = false; rt_table->AddUnresolvedNH(this); - InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_); + const ResolveNH *nh = + static_cast(rt->GetActiveNextHop()); + SecurityGroupList sg_list; + std::string vn = ""; + if (nh->interface()->type() == Interface::VM_INTERFACE) { + const VmInterface *vm_intf = + static_cast(nh->interface()); + vm_intf->CopySgIdList(&sg_list); + if (vm_intf->vn()) { + vn = vm_intf->vn()->GetName(); + } + } + InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_, + nh->interface()->vrf()->GetName(), + nh->interface(), + nh->PolicyEnabled(), + vn, sg_list); rt = NULL; } else { valid = rt->GetActiveNextHop()->IsValid(); @@ -940,16 +978,18 @@ void ReceiveNH::SendObjectLog(AgentLogEvent::type event) const { // ResolveNH routines ///////////////////////////////////////////////////////////////////////////// NextHop *ResolveNHKey::AllocEntry() const { - return new ResolveNH(); + Interface *intf = static_cast + (Agent::GetInstance()->interface_table()->Find(intf_key_.get(), true)); + return new ResolveNH(intf, policy_); } bool ResolveNH::CanAdd() const { return true; } -void ResolveNH::Create( ) { +void ResolveNH::Create(const InterfaceKey *intf, bool policy) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); - req.key.reset(new ResolveNHKey()); + req.key.reset(new ResolveNHKey(intf, policy)); req.data.reset(new ResolveNHData()); NextHopTable::GetInstance()->Process(req); } diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index 708404b4d65..b02593fd37f 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -522,7 +522,7 @@ class ReceiveNH : public NextHop { virtual void Delete(const DBRequest *req) {}; virtual void SendObjectLog(AgentLogEvent::type event) const; virtual bool CanAdd() const; - bool NextHopIsLess(const DBEntry &rhs) const { + virtual bool NextHopIsLess(const DBEntry &rhs) const { const ReceiveNH &a = static_cast(rhs); if (interface_.get() != a.interface_.get()) { return interface_.get() < a.interface_.get(); @@ -551,12 +551,15 @@ class ReceiveNH : public NextHop { ///////////////////////////////////////////////////////////////////////////// class ResolveNHKey : public NextHopKey { public: - ResolveNHKey() : NextHopKey(NextHop::RESOLVE, false) { }; + ResolveNHKey(const InterfaceKey *intf_key, bool policy) : + NextHopKey(NextHop::RESOLVE, policy), + intf_key_(intf_key->Clone()) { }; virtual ~ResolveNHKey() { }; virtual NextHop *AllocEntry() const; private: friend class ResolveNH; + boost::scoped_ptr intf_key_; DISALLOW_COPY_AND_ASSIGN(ResolveNHKey); }; @@ -572,7 +575,8 @@ class ResolveNHData : public NextHopData { class ResolveNH : public NextHop { public: - ResolveNH() : NextHop(RESOLVE, true, false) { }; + ResolveNH(const Interface *intf, bool policy) : + NextHop(RESOLVE, true, policy), interface_(intf) { }; virtual ~ResolveNH() { }; virtual std::string ToString() const { return "Resolve"; }; @@ -582,14 +586,25 @@ class ResolveNH : public NextHop { virtual void SetKey(const DBRequestKey *key) { NextHop::SetKey(key); }; virtual bool CanAdd() const; virtual bool NextHopIsLess(const DBEntry &rhs) const { - return false; + const ResolveNH &a = static_cast(rhs); + if (interface_.get() != a.interface_.get()) { + return interface_.get() < a.interface_.get(); + } + + return policy_ < a.policy_; }; virtual KeyPtr GetDBRequestKey() const { - return DBEntryBase::KeyPtr(new ResolveNHKey()); + boost::scoped_ptr intf_key( + static_cast(interface_->GetDBRequestKey().release())); + return DBEntryBase::KeyPtr(new ResolveNHKey(intf_key.get(), policy_)); }; - - static void Create(); + virtual bool DeleteOnZeroRefCount() const { + return true; + } + static void Create(const InterfaceKey *intf, bool policy); + const Interface* interface() const { return interface_.get();} private: + InterfaceConstRef interface_; DISALLOW_COPY_AND_ASSIGN(ResolveNH); }; @@ -598,8 +613,8 @@ class ResolveNH : public NextHop { ///////////////////////////////////////////////////////////////////////////// class ArpNHKey : public NextHopKey { public: - ArpNHKey(const string &vrf_name, const Ip4Address &ip) : - NextHopKey(NextHop::ARP, false), vrf_key_(vrf_name), dip_(ip) { + ArpNHKey(const string &vrf_name, const Ip4Address &ip, bool policy) : + NextHopKey(NextHop::ARP, policy), vrf_key_(vrf_name), dip_(ip) { } virtual ~ArpNHKey() { }; @@ -613,8 +628,8 @@ class ArpNHKey : public NextHopKey { class ArpNHData : public NextHopData { public: - ArpNHData() : - NextHopData(), intf_key_(NULL), + ArpNHData(InterfaceKey *intf_key) : + NextHopData(), intf_key_(intf_key), mac_(), resolved_(false), valid_(false) { }; ArpNHData(const MacAddress &mac, InterfaceKey *intf_key, diff --git a/src/vnsw/agent/oper/test/test_intf.cc b/src/vnsw/agent/oper/test/test_intf.cc index 82616c308b9..da207a7a8b1 100644 --- a/src/vnsw/agent/oper/test/test_intf.cc +++ b/src/vnsw/agent/oper/test/test_intf.cc @@ -2617,6 +2617,100 @@ TEST_F(IntfTest, InstanceIpDelete) { client->Reset(); } +TEST_F(IntfTest, VcpeIntfAdd) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + CreateVmportWithEcmp(input1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + //Verify that route is pointing to resolve NH + //and the route points to table NH + Ip4Address addr = Ip4Address::from_string("8.1.1.0"); + InetUnicastRouteEntry *rt = RouteGet("vrf1", addr, 24); + const VnEntry *vn = VnGet(1); + EXPECT_TRUE(rt->GetActiveLabel() == vn->table_label()); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind("vrf1", "8.1.1.0", 24)); + + DeleteVmportEnv(input1, 1, true); + client->WaitForIdle(); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + +TEST_F(IntfTest, VcpeSubnetChange) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + CreateVmportWithEcmp(input1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + //Verify that route is pointing to resolve NH + //and the route points to table NH + Ip4Address addr = Ip4Address::from_string("8.1.1.0"); + InetUnicastRouteEntry *rt = RouteGet("vrf1", addr, 24); + const VnEntry *vn = VnGet(1); + EXPECT_TRUE(rt->GetActiveLabel() == vn->table_label()); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE); + + AddSubnetType("subnet", 1, "9.1.1.0", 24); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind("vrf1", "8.1.1.0", 24)); + addr = Ip4Address::from_string("9.1.1.0"); + rt = RouteGet("vrf1", addr, 24); + vn = VnGet(1); + EXPECT_TRUE(rt->GetActiveLabel() == vn->table_label()); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind("vrf1", "9.1.1.0", 24)); + DeleteVmportEnv(input1, 1, true); + client->WaitForIdle(); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + int main(int argc, char **argv) { GETUSERARGS(); diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 8f6f14ff95e..400c5c6c6ce 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -57,7 +57,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), - sub_type_(VmInterface::NONE), ifmap_node_(NULL) { + sub_type_(VmInterface::NONE), ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -82,8 +82,8 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid, parent_(parent), local_preference_(VmInterface::INVALID), oper_dhcp_options_(), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), - vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), - ifmap_node_(NULL) { + vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), ifmap_node_(NULL), + subnet_(0), subnet_plen_(0) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -270,14 +270,31 @@ static void BuildStaticRouteList(VmInterfaceConfigData *data, IFMapNode *node) { LOG(DEBUG, "Error decoding v4 Static Route address " << it->prefix); } } + + IpAddress gw = IpAddress::from_string(it->next_hop, ec); + if (ec) { + gw = IpAddress::from_string("0.0.0.0", ec); + } if (add) { data->static_route_list_.list_.insert - (VmInterface::StaticRoute(data->vrf_name_, ip, plen)); - + (VmInterface::StaticRoute(data->vrf_name_, ip, plen, gw)); } } } +static void BuildResolveRoute(VmInterfaceConfigData *data, IFMapNode *node) { + Subnet *entry = + static_cast(node->GetObject()); + assert(entry); + Ip4Address ip; + boost::system::error_code ec; + ip = Ip4Address::from_string(entry->ip_prefix().ip_prefix, ec); + if (ec.value() == 0) { + data->subnet_ = ip; + data->subnet_plen_ = entry->ip_prefix().ip_prefix_len; + } +} + static void BuildAllowedAddressPairRouteList(VirtualMachineInterface *cfg, VmInterfaceConfigData *data) { for (std::vector::const_iterator it = @@ -508,6 +525,32 @@ bool VmInterface::IsConfigurerSet(VmInterface::Configurer type) { return ((configurer_ & (1 << type)) != 0); } +static bool +AddPhysicalInterface(Agent *agent, IFMapNode *node) { + bool ret = false; + + IFMapNode *physical_node = agent->cfg_listener()-> + FindAdjacentIFMapNode(agent, node, "physical-router"); + if (!physical_node) { + return ret; + } + + autogen::PhysicalRouter *physical_router = + static_cast (physical_node->GetObject()); + if (physical_router->display_name() == agent->host_name()) { + autogen::PhysicalInterface *physical_interface = + static_cast (node->GetObject()); + InterfaceTable *intf_table = agent->interface_table(); + ::PhysicalInterface::Create(intf_table, + physical_interface->display_name(), + agent->fabric_vrf_name(), + true); + ret = true; + } + + return ret; +} + // Virtual Machine Interface is added or deleted into oper DB from Nova // messages. The Config notify is used only to change interface. bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -662,7 +705,26 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { if (adj_node->table() == agent_->cfg()->cfg_route_table()) { BuildStaticRouteList(data, adj_node); } - + + if (adj_node->table() == agent_->cfg()->cfg_subnet_table()) { + BuildResolveRoute(data, adj_node); + } + } + + //Read parent interface name if any + IFMapNode *logical_node = agent_->cfg_listener()-> + FindAdjacentIFMapNode(agent_, node, + "logical-interface"); + if (logical_node) { + IFMapNode *physical_node = agent_->cfg_listener()-> + FindAdjacentIFMapNode(agent_, logical_node, "physical-interface"); + //Add physical interface + if (AddPhysicalInterface(agent_, physical_node)) { + autogen::PhysicalInterface *physical_interface = + static_cast ( + physical_node->GetObject()); + data->parent_ = physical_interface->display_name(); + } } data->sub_type_ = interface_sub_type; @@ -787,6 +849,8 @@ bool VmInterface::Resync(const InterfaceTable *table, bool sg_changed = false; bool ecmp_changed = false; bool local_pref_changed = false; + Ip4Address old_subnet = subnet_; + uint8_t old_subnet_plen = subnet_plen_; if (data) { ret = data->OnResync(table, this, &sg_changed, &ecmp_changed, @@ -817,7 +881,7 @@ bool VmInterface::Resync(const InterfaceTable *table, ApplyConfig(old_ipv4_active, old_l2_active, old_policy, old_vrf.get(), old_addr, old_vxlan_id, old_need_linklocal_ip, sg_changed, old_ipv6_active, old_v6_addr, ecmp_changed, - local_pref_changed); + local_pref_changed, old_subnet, old_subnet_plen); return ret; } @@ -842,7 +906,9 @@ void VmInterface::UpdateL3(bool old_ipv4_active, VrfEntry *old_vrf, const Ip4Address &old_addr, int old_vxlan_id, bool force_update, bool policy_change, bool old_ipv6_active, - const Ip6Address &old_v6_addr) { + const Ip6Address &old_v6_addr, + const Ip4Address &old_subnet, + const uint8_t old_subnet_plen) { UpdateSecurityGroup(); UpdateL3NextHop(old_ipv4_active, old_ipv6_active); UpdateL3TunnelId(force_update, policy_change); @@ -854,6 +920,8 @@ void VmInterface::UpdateL3(bool old_ipv4_active, VrfEntry *old_vrf, UpdateServiceVlan(force_update, policy_change); UpdateAllowedAddressPair(force_update, policy_change); UpdateVrfAssignRule(); + UpdateResolveRoute(old_ipv4_active, force_update, policy_change, + old_vrf, old_subnet, old_subnet_plen); } if (ipv6_active_) { UpdateIpv6InterfaceRoute(old_ipv6_active, force_update, policy_change, @@ -865,7 +933,9 @@ void VmInterface::UpdateL3(bool old_ipv4_active, VrfEntry *old_vrf, void VmInterface::DeleteL3(bool old_ipv4_active, VrfEntry *old_vrf, const Ip4Address &old_addr, bool old_need_linklocal_ip, bool old_ipv6_active, - const Ip6Address &old_v6_addr) { + const Ip6Address &old_v6_addr, + const Ip4Address &old_subnet, + const uint8_t old_subnet_plen) { if (old_ipv4_active) { DeleteIpv4InterfaceRoute(old_vrf, old_addr); } @@ -881,6 +951,7 @@ void VmInterface::DeleteL3(bool old_ipv4_active, VrfEntry *old_vrf, DeleteL3TunnelId(); DeleteVrfAssignRule(); DeleteL3NextHop(old_ipv4_active, old_ipv6_active); + DeleteResolveRoute(old_vrf, old_subnet, old_subnet_plen); } void VmInterface::UpdateVxLan() { @@ -917,7 +988,9 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old int old_vxlan_id, bool old_need_linklocal_ip, bool sg_changed, bool old_ipv6_active, const Ip6Address &old_v6_addr, bool ecmp_mode_changed, - bool local_pref_changed) { + bool local_pref_changed, + const Ip4Address &old_subnet, + uint8_t old_subnet_plen) { //Need not apply config for TOR VMI as it is more of an inidicative //interface. No route addition or NH addition happens for this interface. if (sub_type_ == VmInterface::TOR) @@ -947,10 +1020,12 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old // Add/Del/Update L3 if ((ipv4_active_ || ipv6_active_) && layer3_forwarding_) { UpdateL3(old_ipv4_active, old_vrf, old_addr, old_vxlan_id, force_update, - policy_change, old_ipv6_active, old_v6_addr); + policy_change, old_ipv6_active, old_v6_addr, + old_subnet, old_subnet_plen); } else if ((old_ipv4_active || old_ipv6_active)) { DeleteL3(old_ipv4_active, old_vrf, old_addr, old_need_linklocal_ip, - old_ipv6_active, old_v6_addr); + old_ipv6_active, old_v6_addr, + old_subnet, old_subnet_plen); } // Add/Del/Update L2 @@ -1157,6 +1232,11 @@ bool VmInterface::CopyConfig(const InterfaceTable *table, ret = true; } + if (subnet_ != data->subnet_ || subnet_plen_ != data->subnet_plen_) { + subnet_ = data->subnet_; + subnet_plen_ = data->subnet_plen_; + } + // Copy DHCP options; ret is not modified as there is no dependent action oper_dhcp_options_ = data->oper_dhcp_options_; @@ -1238,6 +1318,12 @@ bool VmInterface::CopyConfig(const InterfaceTable *table, table->operdb()->dependency_manager()->SetObject(ifmap_node_, this); } + if (data->parent_ != Agent::NullString()) { + PhysicalInterfaceKey key(data->parent_); + parent_ = static_cast + (table->agent()->interface_table()->FindActiveEntry(&key)); + assert(parent_ != NULL); + } return ret; } @@ -1753,16 +1839,24 @@ void VmInterface::DeleteMulticastNextHop() { InterfaceNH::DeleteMulticastVmInterfaceNH(GetUuid()); } +Ip4Address VmInterface::GetGateway() const { + Ip4Address ip(0); + if (vn_.get() == NULL) { + return ip; + } + const VnIpam *ipam = vn_->GetIpam(ip_addr_); + if (ipam) { + ip = ipam->default_gw.to_v4(); + } + return ip; +} + // Add/Update route. Delete old route if VRF or address changed void VmInterface::UpdateIpv4InterfaceRoute(bool old_ipv4_active, bool force_update, bool policy_change, VrfEntry * old_vrf, const Ip4Address &old_addr) { - const VnIpam *ipam = vn_->GetIpam(ip_addr_); - Ip4Address ip(0); - if (ipam) { - ip = ipam->default_gw.to_v4(); - } + Ip4Address ip = GetGateway(); // If interface was already active earlier and there is no force_update or // policy_change, return @@ -1840,6 +1934,40 @@ void VmInterface::UpdateIpv6InterfaceRoute(bool old_ipv6_active, bool force_upda } } +void VmInterface::UpdateResolveRoute(bool old_ipv4_active, bool force_update, + bool policy_change, VrfEntry * old_vrf, + const Ip4Address &old_addr, + uint8_t old_plen) { + if (old_ipv4_active == true && force_update == false + && policy_change == false && old_addr == subnet_ && + subnet_plen_ == old_plen) { + return; + } + + if (old_vrf && (old_vrf != vrf_.get() || + old_addr != subnet_ || + subnet_plen_ != old_plen)) { + DeleteResolveRoute(old_vrf, old_addr, old_plen); + } + + if (subnet_.to_ulong() != 0 && vrf_.get() != NULL && vn_.get() != NULL) { + SecurityGroupList sg_id_list; + CopySgIdList(&sg_id_list); + VmInterfaceKey vm_intf_key(AgentKey::ADD_DEL_CHANGE, GetUuid(), ""); + + InetUnicastAgentRouteTable::AddResolveRoute(peer_.get(), vrf_->GetName(), + Address::GetIp4SubnetAddress(subnet_, subnet_plen_), + subnet_plen_, vm_intf_key, vn_->table_label(), + policy_enabled_, vn_->GetName(), sg_id_list); + } +} + +void VmInterface::DeleteResolveRoute(VrfEntry *old_vrf, + const Ip4Address &old_addr, + const uint8_t plen) { + DeleteRoute(old_vrf->GetName(), old_addr, plen); +} + void VmInterface::DeleteIpv4InterfaceRoute(VrfEntry *old_vrf, const Ip4Address &old_addr) { if ((old_vrf == NULL) || (old_addr.to_ulong() == 0)) @@ -2249,6 +2377,18 @@ void VmInterface::AddRoute(const std::string &vrf_name, const IpAddress &addr, return; } +void VmInterface::ResolveRoute(const std::string &vrf_name, const Ip4Address &addr, + uint32_t plen, const std::string &dest_vn, bool policy) { + SecurityGroupList sg_id_list; + CopySgIdList(&sg_id_list); + VmInterfaceKey vm_intf_key(AgentKey::ADD_DEL_CHANGE, GetUuid(), ""); + + InetUnicastAgentRouteTable::AddResolveRoute(peer_.get(), vrf_name, + Address::GetIp4SubnetAddress(addr, plen), + plen, vm_intf_key, vn_->table_label(), + policy, dest_vn, sg_id_list); +} + void VmInterface::DeleteRoute(const std::string &vrf_name, const IpAddress &addr, uint32_t plen) { InetUnicastAgentRouteTable::Delete(peer_.get(), vrf_name, addr, plen); @@ -2434,18 +2574,18 @@ void VmInterface::FloatingIpList::Remove(FloatingIpSet::iterator &it) { // StaticRoute routines ///////////////////////////////////////////////////////////////////////////// VmInterface::StaticRoute::StaticRoute() : - ListEntry(), vrf_(""), addr_(), plen_(0) { + ListEntry(), vrf_(""), addr_(), plen_(0), gw_() { } VmInterface::StaticRoute::StaticRoute(const StaticRoute &rhs) : ListEntry(rhs.installed_, rhs.del_pending_), vrf_(rhs.vrf_), - addr_(rhs.addr_), plen_(rhs.plen_) { + addr_(rhs.addr_), plen_(rhs.plen_), gw_(rhs.gw_) { } VmInterface::StaticRoute::StaticRoute(const std::string &vrf, const IpAddress &addr, - uint32_t plen) : - ListEntry(), vrf_(vrf), addr_(addr), plen_(plen) { + uint32_t plen, const IpAddress &gw) : + ListEntry(), vrf_(vrf), addr_(addr), plen_(plen), gw_(gw) { } VmInterface::StaticRoute::~StaticRoute() { @@ -2486,10 +2626,21 @@ void VmInterface::StaticRoute::Activate(VmInterface *interface, if (addr_.is_v4()) { ecmp = interface->ecmp(); } - interface->AddRoute(vrf_, addr_, plen_, - interface->vn_->GetName(), - interface->policy_enabled(), - ecmp, IpAddress()); + Ip4Address gw_ip(0); + if (gw_.is_v4() && addr_.is_v4() && gw_.to_v4() != gw_ip) { + SecurityGroupList sg_id_list; + interface->CopySgIdList(&sg_id_list); + InetUnicastAgentRouteTable::AddGatewayRoute(interface->peer_.get(), + vrf_, addr_.to_v4(), + plen_, gw_.to_v4(), interface->vn_->GetName(), + interface->vn_->table_label(), + sg_id_list); + } else { + interface->AddRoute(vrf_, addr_, plen_, + interface->vn_->GetName(), + interface->policy_enabled(), + ecmp, IpAddress()); + } } installed_ = true; @@ -2962,6 +3113,31 @@ void VmInterface::InstanceIpSync(InterfaceTable *table, IFMapNode *node) { } +void VmInterface::SubnetSync(InterfaceTable *table, IFMapNode *node) { + CfgListener *cfg_listener = table->agent()->cfg_listener(); + if (cfg_listener->SkipNode(node)) { + return; + } + + DBGraph *graph = + static_cast (node->table())->GetGraph();; + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + IFMapNode *adj = static_cast(iter.operator->()); + if (table->agent()->cfg_listener()->SkipNode(adj)) { + continue; + } + + if (adj->table() == + table->agent()->cfg()->cfg_vm_interface_table()) { + DBRequest req; + if (table->IFNodeToReq(adj, req)) { + table->Enqueue(&req); + } + } + } +} + void VmInterface::FloatingIpVnSync(InterfaceTable *table, IFMapNode *node) { CfgListener *cfg_listener = table->agent()->cfg_listener(); if (cfg_listener->SkipNode(node)) { diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index b1d47784b29..0d0ee179db5 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -128,7 +128,7 @@ class VmInterface : public Interface { StaticRoute(); StaticRoute(const StaticRoute &rhs); StaticRoute(const std::string &vrf, const IpAddress &addr, - uint32_t plen); + uint32_t plen, const IpAddress &gw); virtual ~StaticRoute(); bool operator() (const StaticRoute &lhs, const StaticRoute &rhs) const; @@ -140,6 +140,7 @@ class VmInterface : public Interface { mutable std::string vrf_; IpAddress addr_; uint32_t plen_; + IpAddress gw_; }; typedef std::set StaticRouteSet; @@ -321,6 +322,8 @@ class VmInterface : public Interface { void SetConfigurer(VmInterface::Configurer type); void ResetConfigurer(VmInterface::Configurer type); bool CanBeDeleted() const {return (configurer_ == 0);} + const Ip4Address& subnet() const { return subnet_;} + const uint8_t subnet_plen() const { return subnet_plen_;} Interface::MirrorDirection mirror_direction() const { return mirror_direction_; @@ -405,6 +408,7 @@ class VmInterface : public Interface { static void FloatingIpSync(InterfaceTable *table, IFMapNode *node); static void FloatingIpVrfSync(InterfaceTable *table, IFMapNode *node); static void VnSync(InterfaceTable *table, IFMapNode *node); + static void SubnetSync(InterfaceTable *table, IFMapNode *node); static void VmSync(InterfaceTable *table, IFMapNode *node); void AllocL2MplsLabel(bool force_update, bool policy_change); @@ -420,6 +424,7 @@ class VmInterface : public Interface { bool GetIpamDhcpOptions( std::vector *options, bool ipv6) const; const Peer *peer() const; + Ip4Address GetGateway() const; private: friend struct VmInterfaceConfigData; friend struct VmInterfaceNovaData; @@ -438,6 +443,8 @@ class VmInterface : public Interface { bool ecmp, const IpAddress &gw_ip); void DeleteRoute(const std::string &vrf_name, const IpAddress &ip, uint32_t plen); + void ResolveRoute(const std::string &vrf_name, const Ip4Address &addr, + uint32_t plen, const std::string &dest_vn, bool policy); void ServiceVlanAdd(ServiceVlan &entry); void ServiceVlanDel(ServiceVlan &entry); void ServiceVlanRouteAdd(const ServiceVlan &entry); @@ -460,15 +467,17 @@ class VmInterface : public Interface { int old_vxlan_id, bool old_need_linklocal_ip, bool sg_changed, bool old_ipv6_active, const Ip6Address &old_v6_addr, bool ecmp_changed, - bool local_pref_changed); - + bool local_pref_changed, const Ip4Address &old_subnet, + const uint8_t old_subnet_plen); void UpdateL3(bool old_ipv4_active, VrfEntry *old_vrf, const Ip4Address &old_addr, int old_vxlan_id, bool force_update, bool policy_change, bool old_ipv6_active, - const Ip6Address &old_v6_addr); + const Ip6Address &old_v6_addr, const Ip4Address &subnet, + const uint8_t old_subnet_plen); void DeleteL3(bool old_ipv4_active, VrfEntry *old_vrf, const Ip4Address &old_addr, bool old_need_linklocal_ip, - bool old_ipv6_active, const Ip6Address &old_v6_addr); + bool old_ipv6_active, const Ip6Address &old_v6_addr, + const Ip4Address &old_subnet, const uint8_t old_subnet_plen); void UpdateL2(bool old_l2_active, VrfEntry *old_vrf, int old_vxlan_id, bool force_update, bool policy_change); void DeleteL2(bool old_l2_active, VrfEntry *old_vrf); @@ -501,6 +510,11 @@ class VmInterface : public Interface { const Ip6Address &old_addr); void DeleteIpv6InterfaceRoute(VrfEntry *old_vrf, const Ip6Address &old_addr); + void UpdateResolveRoute(bool old_ipv4_active, bool force_update, + bool policy_change, VrfEntry * old_vrf, + const Ip4Address &old_addr, uint8_t old_plen); + void DeleteResolveRoute(VrfEntry *old_vrf, + const Ip4Address &old_addr, const uint8_t old_plen); void DeleteInterfaceNH(); void UpdateMetadataRoute(bool old_ipv4_active, VrfEntry *old_vrf); void DeleteMetadataRoute(bool old_ipv4_active, VrfEntry *old_vrf, @@ -578,6 +592,8 @@ class VmInterface : public Interface { VmInterface::SubType sub_type_; uint8_t configurer_; IFMapNode *ifmap_node_; + Ip4Address subnet_; + uint8_t subnet_plen_; DISALLOW_COPY_AND_ASSIGN(VmInterface); }; @@ -685,7 +701,7 @@ struct VmInterfaceConfigData : public VmInterfaceData { mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), sub_type_(VmInterface::NONE), - parent_(""), ifmap_node_(NULL) { + parent_(""), ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { } virtual ~VmInterfaceConfigData() { } @@ -730,6 +746,8 @@ struct VmInterfaceConfigData : public VmInterfaceData { VmInterface::SubType sub_type_; std::string parent_; IFMapNode *ifmap_node_; + Ip4Address subnet_; + uint8_t subnet_plen_; }; // Definition for structures when request queued from Nova diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index 1e9f77372c3..36e940e61ce 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -328,9 +328,18 @@ bool VnTable::ChangeHandler(DBEntry *entry, const DBRequest *req) { VrfEntry *vrf = static_cast (Agent::GetInstance()->vrf_table()->FindActiveEntry(&vrf_key)); if (vrf != old_vrf) { - if (!vrf) + if (!vrf) { DeleteAllIpamRoutes(vn); + if (vn->table_label()) { + MplsLabel::Delete(vn->table_label()); + vn->set_table_label(0); + } + } vn->vrf_ = vrf; + if (vrf) { + vn->set_table_label(Agent::GetInstance()->mpls_table()->AllocLabel()); + MplsLabel::CreateTableLabel(vn->table_label(), data->vrf_name_, false); + } ret = true; } @@ -370,6 +379,10 @@ bool VnTable::ChangeHandler(DBEntry *entry, const DBRequest *req) { bool VnTable::Delete(DBEntry *entry, const DBRequest *req) { VnEntry *vn = static_cast(entry); DeleteAllIpamRoutes(vn); + if (vn->table_label()) { + MplsLabel::Delete(vn->table_label()); + vn->set_table_label(0); + } vn->SendObjectLog(AgentLogEvent::DELETE); return true; } @@ -882,6 +895,7 @@ bool VnEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const { data.set_ipv4_forwarding(layer3_forwarding()); data.set_layer2_forwarding(layer2_forwarding()); data.set_admin_state(admin_state()); + data.set_table_label(table_label()); std::vector &list = const_cast&>(resp->get_vn_list()); diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index 7c3bda69c95..d82dcc53c41 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -144,7 +144,7 @@ struct VnData : public AgentData { class VnEntry : AgentRefCount, public AgentDBEntry { public: VnEntry(uuid id) : uuid_(id), vxlan_id_(0), vnid_(0), layer2_forwarding_(true), - layer3_forwarding_(true), admin_state_(true) { } + layer3_forwarding_(true), admin_state_(true), table_label_(0) { } virtual ~VnEntry() { }; virtual bool IsLess(const DBEntry &rhs) const; @@ -187,6 +187,10 @@ class VnEntry : AgentRefCount, public AgentDBEntry { bool layer2_forwarding() const {return layer2_forwarding_;}; bool layer3_forwarding() const {return layer3_forwarding_;}; bool admin_state() const {return admin_state_;} + uint32_t table_label() const { return table_label_;} + void set_table_label(uint32_t label) { + table_label_ = label; + } AgentDBTable *DBToTable() const; uint32_t GetRefCount() const { @@ -214,6 +218,7 @@ class VnEntry : AgentRefCount, public AgentDBEntry { bool layer3_forwarding_; bool admin_state_; VxLanIdRef vxlan_id_ref_; + uint32_t table_label_; DISALLOW_COPY_AND_ASSIGN(VnEntry); }; diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.cc b/src/vnsw/agent/physical_devices/tables/physical_port.cc index 33e48944771..2cae4d5f266 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_port.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,14 @@ bool PhysicalPortEntry::Copy(PhysicalPortTable *table, if (dev != device_.get()) { device_.reset(dev); ret = true; + + if (device_ && device_->name() == table->agent()->host_name()) { + //Create a physical interface + InterfaceTable *intf_table = table->agent()->interface_table(); + PhysicalInterface::Create(intf_table, name_, + table->agent()->fabric_vrf_name(), + false); + } } return ret; diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 1943a2b499c..00901adea65 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -201,6 +201,12 @@ static bool NhDecode(const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, break; } + case NextHop::VRF: { + const VrfNH *vrf_nh = static_cast(nh); + out->vrf_ = vrf_nh->GetVrf(); + break; + } + case NextHop::TUNNEL: { if (pkt->family == Address::INET) { const InetUnicastRouteEntry *rt = @@ -223,6 +229,20 @@ static bool NhDecode(const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, break; } + case NextHop::ARP: { + const ArpNH *arp_nh = static_cast(nh); + out->nh_ = arp_nh->GetInterface()->flow_key_nh()->id(); + out->intf_ = arp_nh->GetInterface(); + break; + } + + case NextHop::RESOLVE: { + const ResolveNH *rsl_nh = static_cast(nh); + out->nh_ = rsl_nh->interface()->flow_key_nh()->id(); + out->intf_ = rsl_nh->interface(); + break; + } + default: out->intf_ = NULL; break; @@ -277,7 +297,7 @@ static const VnEntry *InterfaceToVn(const Interface *intf) { } static bool IntfHasFloatingIp(const Interface *intf, Address::Family family) { - if (intf->type() != Interface::VM_INTERFACE) + if (!intf || intf->type() != Interface::VM_INTERFACE) return NULL; return static_cast(intf)->HasFloatingIp(family); } @@ -934,6 +954,7 @@ void PktFlowInfo::EgressProcess(const PktInfo *pkt, PktControlInfo *in, UpdateRoute(&out->rt_, out->vrf_,pkt->ip_daddr, flow_dest_plen_map); UpdateRoute(&in->rt_, out->vrf_,pkt->ip_saddr, flow_source_plen_map); + if (out->intf_) { out->vn_ = InterfaceToVn(out->intf_); } @@ -949,6 +970,21 @@ void PktFlowInfo::EgressProcess(const PktInfo *pkt, PktControlInfo *in, } } + if (out->rt_) { + if (out->rt_->GetActiveNextHop()->GetType() == NextHop::ARP || + out->rt_->GetActiveNextHop()->GetType() == NextHop::RESOLVE) { + //If a packet came with mpls label pointing to + //vrf NH, then we need to do a route lookup + //and set the nexthop for reverse flow properly + //as mpls pointed NH would not be used for reverse flow + if (RouteToOutInfo(out->rt_, pkt, this, in, out)) { + if (out->intf_) { + out->vn_ = InterfaceToVn(out->intf_); + } + } + } + } + return; } @@ -1011,7 +1047,6 @@ bool PktFlowInfo::Process(const PktInfo *pkt, PktControlInfo *in, short_flow_reason = FlowEntry::SHORT_NO_DST_ROUTE; return false; } - flow_source_vrf = static_cast(in->rt_)->vrf_id(); flow_dest_vrf = out->rt_->vrf_id(); diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index db883e6f8a3..fbb8bfb78ff 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -617,7 +617,6 @@ bool PktHandler::IsValidInterface(uint16_t ifindex, Interface **interface) { if (!vm_itf->layer3_forwarding()) { PKT_TRACE(Err, "layer3 not enabled for interface index <" << ifindex << ">"); - agent_->stats()->incr_pkt_dropped(); return false; } } diff --git a/src/vnsw/agent/services/arp_entry.cc b/src/vnsw/agent/services/arp_entry.cc index 88f78b7c3a7..da0c68a56ef 100644 --- a/src/vnsw/agent/services/arp_entry.cc +++ b/src/vnsw/agent/services/arp_entry.cc @@ -9,20 +9,46 @@ #include "oper/route_common.h" ArpEntry::ArpEntry(boost::asio::io_service &io, ArpHandler *handler, - ArpKey &key, State state) - : key_(key), state_(state), retry_count_(0), handler_(handler), - arp_timer_(NULL) { - arp_timer_ = TimerManager::CreateTimer(io, "Arp Entry timer", - TaskScheduler::GetInstance()->GetTaskId("Agent::Services"), - PktHandler::ARP); + ArpKey &key, const VrfEntry *vrf, State state, + const Interface *itf) + : io_(io), key_(key), nh_vrf_(vrf), state_(state), retry_count_(0), + handler_(handler), arp_timer_(NULL), interface_(itf) { + if (!IsDerived()) { + arp_timer_ = TimerManager::CreateTimer(io, "Arp Entry timer", + TaskScheduler::GetInstance()->GetTaskId("Agent::Services"), + PktHandler::ARP); + } } ArpEntry::~ArpEntry() { - arp_timer_->Cancel(); - TimerManager::DeleteTimer(arp_timer_); + if (!IsDerived()) { + arp_timer_->Cancel(); + TimerManager::DeleteTimer(arp_timer_); + } +} + +void ArpEntry::HandleDerivedArpRequest() { + ArpProto *arp_proto = handler_->agent()->GetArpProto(); + //Add ArpRoute for Derived entry + AddArpRoute(IsResolved()); + + ArpKey key(key_.ip, nh_vrf_); + ArpEntry *entry = arp_proto->FindArpEntry(key); + if (entry) { + entry->HandleArpRequest(); + } else { + entry = new ArpEntry(io_, handler_.get(), key, nh_vrf_, ArpEntry::INITING, + interface_); + arp_proto->AddArpEntry(entry); + entry->HandleArpRequest(); + } } bool ArpEntry::HandleArpRequest() { + if (IsDerived()) { + HandleDerivedArpRequest(); + return true; + } if (IsResolved()) AddArpRoute(true); else { @@ -36,14 +62,21 @@ bool ArpEntry::HandleArpRequest() { } void ArpEntry::HandleArpReply(const MacAddress &mac) { + + if (IsDerived()) { + /* We don't expect ARP replies in derived Vrf */ + return; + } if ((state_ == ArpEntry::RESOLVING) || (state_ == ArpEntry::ACTIVE) || (state_ == ArpEntry::INITING) || (state_ == ArpEntry::RERESOLVING)) { ArpProto *arp_proto = handler_->agent()->GetArpProto(); arp_timer_->Cancel(); retry_count_ = 0; mac_address_ = mac; - if (state_ == ArpEntry::RESOLVING) + if (state_ == ArpEntry::RESOLVING) { arp_proto->IncrementStatsResolved(); + arp_proto->IncrementStatsResolved(interface_->id()); + } state_ = ArpEntry::ACTIVE; StartTimer(arp_proto->aging_timeout(), ArpProto::AGING_TIMER_EXPIRED); AddArpRoute(true); @@ -77,7 +110,7 @@ bool ArpEntry::RetryExpiry() { bool ArpEntry::AgingExpiry() { Ip4Address ip(key_.ip); const string& vrf_name = key_.vrf->GetName(); - ArpNHKey nh_key(vrf_name, ip); + ArpNHKey nh_key(vrf_name, ip, false); ArpNH *arp_nh = static_cast(handler_->agent()->nexthop_table()-> FindActiveEntry(&nh_key)); if (!arp_nh) { @@ -114,25 +147,49 @@ bool ArpEntry::IsResolved() { return (state_ & (ArpEntry::ACTIVE | ArpEntry::RERESOLVING)); } +bool ArpEntry::IsDerived() { + if (key_.vrf != nh_vrf_) { + return true; + } + return false; +} + void ArpEntry::StartTimer(uint32_t timeout, uint32_t mtype) { arp_timer_->Cancel(); arp_timer_->Start(timeout, boost::bind(&ArpProto::TimerExpiry, handler_->agent()->GetArpProto(), - key_, mtype)); + key_, mtype, interface_)); } void ArpEntry::SendArpRequest() { + assert(!IsDerived()); Agent *agent = handler_->agent(); ArpProto *arp_proto = agent->GetArpProto(); - uint16_t itf_index = arp_proto->ip_fabric_interface_index(); - Ip4Address ip = agent->router_id(); + uint32_t vrf_id = VrfEntry::kInvalidIndex; + uint32_t intf_id = arp_proto->ip_fabric_interface_index(); + Ip4Address ip; + MacAddress smac; + if (interface_->type() == Interface::VM_INTERFACE) { + const VmInterface *vmi = static_cast(interface_); + ip = vmi->GetGateway(); + vrf_id = nh_vrf_->vrf_id(); + if (vmi->parent()) { + intf_id = vmi->parent()->id(); + smac = vmi->parent()->mac(); + } + } else { + ip = agent->router_id(); + VrfEntry *vrf = + agent->vrf_table()->FindVrfFromName(agent->fabric_vrf_name()); + if (vrf) { + vrf_id = vrf->vrf_id(); + } + smac = interface_->mac(); + } - VrfEntry *vrf = - agent->vrf_table()->FindVrfFromName(agent->fabric_vrf_name()); - if (vrf) { - handler_->SendArp(ARPOP_REQUEST, arp_proto->ip_fabric_interface_mac(), - ip.to_ulong(), MacAddress(), key_.ip, itf_index, - vrf->vrf_id()); + if (vrf_id != VrfEntry::kInvalidIndex) { + handler_->SendArp(ARPOP_REQUEST, smac, ip.to_ulong(), + MacAddress(), key_.ip, intf_id, vrf_id); } StartTimer(arp_proto->retry_timeout(), ArpProto::RETRY_TIMER_EXPIRED); @@ -147,7 +204,7 @@ void ArpEntry::AddArpRoute(bool resolved) { Ip4Address ip(key_.ip); const string& vrf_name = key_.vrf->GetName(); - ArpNHKey nh_key(vrf_name, ip); + ArpNHKey nh_key(nh_vrf_->GetName(), ip, false); ArpNH *arp_nh = static_cast(handler_->agent()->nexthop_table()-> FindActiveEntry(&nh_key)); @@ -155,15 +212,43 @@ void ArpEntry::AddArpRoute(bool resolved) { if (arp_nh && arp_nh->GetResolveState() && mac.CompareTo(arp_nh->GetMac()) == 0) { // MAC address unchanged, ignore - return; + if (!IsDerived()) { + return; + } else { + /* Return if the route is already existing */ + InetUnicastRouteKey *rt_key = new InetUnicastRouteKey( + handler_->agent()->local_peer(), vrf_name, ip, 32); + AgentRoute *entry = key_.vrf->GetInet4UnicastRouteTable()-> + FindActiveEntry(rt_key); + delete rt_key; + if (entry) { + return; + } + resolved = true; + } } ARP_TRACE(Trace, "Add", ip.to_string(), vrf_name, mac.ToString()); + AgentRoute *entry = key_.vrf->GetInet4UnicastRouteTable()->FindLPM(ip); + + bool policy = false; + SecurityGroupList sg; + std::string vn = " ";; + if (entry) { + policy = entry->GetActiveNextHop()->PolicyEnabled(); + sg = entry->GetActivePath()->sg_list(); + vn = entry->GetActivePath()->dest_vn_name(); + } - Interface *itf = handler_->agent()->GetArpProto()->ip_fabric_interface(); + const Interface *itf = NULL; + if (interface_->type() == Interface::VM_INTERFACE) { + itf = interface_; + } else { + itf = handler_->agent()->GetArpProto()->ip_fabric_interface(); + } handler_->agent()->fabric_inet4_unicast_table()->ArpRoute( - DBRequest::DB_ENTRY_ADD_CHANGE, ip, mac, - vrf_name, *itf, resolved, 32); + DBRequest::DB_ENTRY_ADD_CHANGE, vrf_name, ip, mac, + nh_vrf_->GetName(), *itf, resolved, 32, policy, vn, sg); } bool ArpEntry::DeleteArpRoute() { @@ -173,7 +258,7 @@ bool ArpEntry::DeleteArpRoute() { Ip4Address ip(key_.ip); const string& vrf_name = key_.vrf->GetName(); - ArpNHKey nh_key(vrf_name, ip); + ArpNHKey nh_key(nh_vrf_->GetName(), ip, false); ArpNH *arp_nh = static_cast(handler_->agent()->nexthop_table()-> FindActiveEntry(&nh_key)); if (!arp_nh) @@ -182,9 +267,17 @@ bool ArpEntry::DeleteArpRoute() { MacAddress mac = mac_address_; ARP_TRACE(Trace, "Delete", ip.to_string(), vrf_name, mac.ToString()); - Interface *itf = handler_->agent()->GetArpProto()->ip_fabric_interface(); handler_->agent()->fabric_inet4_unicast_table()->ArpRoute( - DBRequest::DB_ENTRY_DELETE, ip, mac, vrf_name, - *itf, false, 32); + DBRequest::DB_ENTRY_DELETE, vrf_name, ip, mac, vrf_name, + *interface_, false, 32, false, " ", SecurityGroupList()); return false; } + +void ArpEntry::Resync(bool policy, const std::string &vn, + const SecurityGroupList &sg) { + Ip4Address ip(key_.ip); + handler_->agent()->fabric_inet4_unicast_table()->ArpRoute( + DBRequest::DB_ENTRY_ADD_CHANGE, key_.vrf->GetName(), ip, + mac_address_, nh_vrf_->GetName(), *interface_, IsResolved(), + 32, policy, vn, sg); +} diff --git a/src/vnsw/agent/services/arp_entry.h b/src/vnsw/agent/services/arp_entry.h index 3154982128f..b1776fcf99d 100644 --- a/src/vnsw/agent/services/arp_entry.h +++ b/src/vnsw/agent/services/arp_entry.h @@ -29,12 +29,14 @@ class ArpEntry { }; ArpEntry(boost::asio::io_service &io, ArpHandler *handler, - ArpKey &key, State state); + ArpKey &key, const VrfEntry *vrf, State state, + const Interface *itf); virtual ~ArpEntry(); const ArpKey &key() const { return key_; } State state() const { return state_; } const MacAddress &mac_address() const { return mac_address_; } + const Interface *interface() const { return interface_; } bool HandleArpRequest(); void HandleArpReply(const MacAddress &); @@ -43,18 +45,24 @@ class ArpEntry { void SendGratuitousArp(); bool DeleteArpRoute(); bool IsResolved(); + void Resync(bool policy, const std::string &vn, const SecurityGroupList &sg); private: void StartTimer(uint32_t timeout, uint32_t mtype); void SendArpRequest(); void AddArpRoute(bool resolved); + void HandleDerivedArpRequest(); + bool IsDerived(); + boost::asio::io_service &io_; ArpKey key_; + const VrfEntry *nh_vrf_; MacAddress mac_address_; State state_; int retry_count_; boost::scoped_ptr handler_; Timer *arp_timer_; + const Interface *interface_; DISALLOW_COPY_AND_ASSIGN(ArpEntry); }; diff --git a/src/vnsw/agent/services/arp_handler.cc b/src/vnsw/agent/services/arp_handler.cc index 22e01ef49d4..c7d56dc6a9f 100644 --- a/src/vnsw/agent/services/arp_handler.cc +++ b/src/vnsw/agent/services/arp_handler.cc @@ -87,16 +87,16 @@ bool ArpHandler::HandlePacket() { ARP_TRACE(Error, "Received ARP packet from invalid / inactive interface"); return true; } - if (itf->type() == Interface::VM_INTERFACE) { - const VmInterface *vm_itf = static_cast(itf); - if (!vm_itf->layer3_forwarding()) { - ARP_TRACE(Error, "Received ARP packet on ipv4 disabled interface"); - return true; - } - } - const VrfEntry *vrf = itf->vrf(); + const VrfEntry *vrf = agent()->vrf_table()->FindVrfFromId(pkt_info_->vrf); if (!vrf || !vrf->IsActive()) { + arp_proto->IncrementStatsInvalidVrf(); + ARP_TRACE(Error, "ARP : AgentHdr " + itf->name() + + " has no / inactive VRF "); + return true; + } + const VrfEntry *nh_vrf = itf->vrf(); + if (!nh_vrf || !nh_vrf->IsActive()) { arp_proto->IncrementStatsInvalidVrf(); ARP_TRACE(Error, "ARP : Interface " + itf->name() + " has no / inactive VRF"); @@ -123,6 +123,12 @@ bool ArpHandler::HandlePacket() { arp_addr.to_string()); return true; } + if (route->GetActiveNextHop()->GetType() == NextHop::RESOLVE) { + const ResolveNH *nh = + static_cast(route->GetActiveNextHop()); + itf = nh->interface(); + nh_vrf = itf->vrf(); + } } ArpKey key(arp_tpa_, vrf); @@ -131,11 +137,13 @@ bool ArpHandler::HandlePacket() { switch (arp_cmd) { case ARPOP_REQUEST: { arp_proto->IncrementStatsArpReq(); + arp_proto->IncrementStatsArpRequest(itf->id()); if (entry) { entry->HandleArpRequest(); return true; } else { - entry = new ArpEntry(io_, this, key, ArpEntry::INITING); + entry = new ArpEntry(io_, this, key, nh_vrf, ArpEntry::INITING, + itf); arp_proto->AddArpEntry(entry); entry->HandleArpRequest(); return false; @@ -144,6 +152,7 @@ bool ArpHandler::HandlePacket() { case ARPOP_REPLY: { arp_proto->IncrementStatsArpReplies(); + arp_proto->IncrementStatsArpReply(itf->id()); if (itf->type() == Interface::VM_INTERFACE) { uint32_t ip; memcpy(&ip, arp_->arp_spa, sizeof(ip)); @@ -152,12 +161,17 @@ bool ArpHandler::HandlePacket() { agent()->oper_db()->route_preference_module()-> EnqueueTrafficSeen(Ip4Address(ip), 32, itf->id(), vrf->vrf_id()); + if(entry) { + entry->HandleArpReply(MacAddress(arp_->arp_sha)); + } return true; - } else if(entry) { + } + if(entry) { entry->HandleArpReply(MacAddress(arp_->arp_sha)); return true; - } else { - entry = new ArpEntry(io_, this, key, ArpEntry::INITING); + } else { + entry = new ArpEntry(io_, this, key, nh_vrf, ArpEntry::INITING, + itf); arp_proto->AddArpEntry(entry); entry->HandleArpReply(MacAddress(arp_->arp_sha)); arp_ = NULL; @@ -180,7 +194,7 @@ bool ArpHandler::HandlePacket() { entry->HandleArpReply(MacAddress(arp_->arp_sha)); return true; } else { - entry = new ArpEntry(io_, this, key, ArpEntry::INITING); + entry = new ArpEntry(io_, this, key, key.vrf, ArpEntry::INITING, itf); entry->HandleArpReply(MacAddress(arp_->arp_sha)); arp_proto->AddArpEntry(entry); arp_ = NULL; @@ -195,6 +209,13 @@ bool ArpHandler::HandlePacket() { } } +/* This API is invoked from the following paths + - NextHop notification for ARP_NH + - ARP Timer expiry + - Sending Gratituous ARP for Receive Nexthops + In all these above paths we expect route_vrf and nh_vrf for ArpRoute to + be same + */ bool ArpHandler::HandleMessage() { bool ret = true; ArpProto::ArpIpc *ipc = static_cast(pkt_info_->ipc); @@ -203,11 +224,13 @@ bool ArpHandler::HandleMessage() { case ArpProto::ARP_RESOLVE: { ArpEntry *entry = arp_proto->FindArpEntry(ipc->key); if (!entry) { - entry = new ArpEntry(io_, this, ipc->key, ArpEntry::INITING); + entry = new ArpEntry(io_, this, ipc->key, ipc->key.vrf, + ArpEntry::INITING, ipc->interface); arp_proto->AddArpEntry(entry); ret = false; } arp_proto->IncrementStatsArpReq(); + arp_proto->IncrementStatsArpRequest(ipc->interface->id()); entry->HandleArpRequest(); break; } @@ -215,7 +238,8 @@ bool ArpHandler::HandleMessage() { case ArpProto::ARP_SEND_GRATUITOUS: { if (!arp_proto->gratuitous_arp_entry()) { arp_proto->set_gratuitous_arp_entry( - new ArpEntry(io_, this, ipc->key, ArpEntry::ACTIVE)); + new ArpEntry(io_, this, ipc->key, ipc->key.vrf, + ArpEntry::ACTIVE, ipc->interface)); ret = false; } arp_proto->gratuitous_arp_entry()->SendGratuitousArp(); diff --git a/src/vnsw/agent/services/arp_proto.cc b/src/vnsw/agent/services/arp_proto.cc index b89bb49e7ef..21cb59c925b 100644 --- a/src/vnsw/agent/services/arp_proto.cc +++ b/src/vnsw/agent/services/arp_proto.cc @@ -80,8 +80,10 @@ void ArpProto::VrfNotify(DBTablePartBase *part, DBEntryBase *entry) { } } -ArpDBState::ArpDBState(ArpVrfState *vrf_state, uint32_t vrf_id, IpAddress ip) : - vrf_state_(vrf_state), arp_req_timer_(NULL), vrf_id_(vrf_id), vm_ip_(ip) { +ArpDBState::ArpDBState(ArpVrfState *vrf_state, uint32_t vrf_id, IpAddress ip, + uint8_t plen) : vrf_state_(vrf_state), + arp_req_timer_(NULL), vrf_id_(vrf_id), vm_ip_(ip), plen_(plen), + sg_list_(0), policy_(false), resolve_route_(false) { } ArpDBState::~ArpDBState() { @@ -156,7 +158,6 @@ void ArpDBState::SendArpRequestForAllIntf(const InetUnicastRouteEntry *route) { //Ignore non vm interface nexthop continue; } - if (path->subnet_gw_ip().is_v4() == false) { continue; } @@ -188,6 +189,68 @@ void ArpDBState::SendArpRequestForAllIntf(const InetUnicastRouteEntry *route) { } } +void ArpDBState::UpdateArpRoutes(const InetUnicastRouteEntry *rt) { + int plen = rt->plen(); + uint32_t start_ip = rt->addr().to_v4().to_ulong(); + ArpKey start_key(start_ip, rt->vrf()); + + ArpProto::ArpIterator start_iter = + vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key); + + if (start_iter->first.vrf != rt->vrf()) { + return; + } + + + while (IsIp4SubnetMember(Ip4Address(start_iter->first.ip), + rt->addr().to_v4(), plen)) { + start_iter->second->Resync(policy_, vn_, sg_list_); + start_iter++; + } +} + +void ArpDBState::Delete(const InetUnicastRouteEntry *rt) { + int plen = rt->plen(); + uint32_t start_ip = rt->addr().to_v4().to_ulong(); + + ArpKey start_key(start_ip, rt->vrf()); + + ArpProto::ArpIterator start_iter = + vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key); + + if (start_iter->first.vrf != rt->vrf()) { + return; + } + + while (IsIp4SubnetMember(Ip4Address(start_iter->first.ip), + rt->addr().to_v4(), plen)) { + ArpProto::ArpIterator tmp = start_iter++; + if (tmp->second->DeleteArpRoute()) { + vrf_state_->arp_proto->DeleteArpEntry(tmp->second); + } + } +} + +void ArpDBState::Update(const InetUnicastRouteEntry *rt) { + if (rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE) { + resolve_route_ = true; + } + + bool policy = rt->GetActiveNextHop()->PolicyEnabled(); + const SecurityGroupList sg = rt->GetActivePath()->sg_list(); + + + if (policy_ != policy || sg != sg_list_ || + vn_ != rt->GetActivePath()->dest_vn_name()) { + policy_ = policy; + sg_list_ = sg; + vn_ = rt->GetActivePath()->dest_vn_name(); + if (resolve_route_) { + UpdateArpRoutes(rt); + } + } +} + void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) { InetUnicastRouteEntry *route = static_cast(entry); @@ -209,7 +272,8 @@ void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) { } if (!state) { - state = new ArpDBState(this, route->vrf_id(), route->addr()); + state = new ArpDBState(this, route->vrf_id(), route->addr(), + route->plen()); entry->SetState(part->parent(), route_table_listener_id, state); } @@ -218,12 +282,14 @@ void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) { arp_proto->del_gratuitous_arp_entry(); //Send Grat ARP arp_proto->SendArpIpc(ArpProto::ARP_SEND_GRATUITOUS, - route->addr().to_v4().to_ulong(), route->vrf()); + route->addr().to_v4().to_ulong(), route->vrf(), + arp_proto->ip_fabric_interface()); } //Check if there is a local VM path, if yes send a //ARP request, to trigger route preference state machine if (state && route->vrf()->GetName() != agent->fabric_vrf_name()) { + state->Update(route); state->SendArpRequestForAllIntf(route); } } @@ -258,16 +324,26 @@ ArpVrfState::ArpVrfState(Agent *agent_ptr, ArpProto *proto, VrfEntry *vrf_entry, void ArpProto::InterfaceNotify(DBEntryBase *entry) { Interface *itf = static_cast(entry); if (entry->IsDeleted()) { + InterfaceArpMap::iterator it = interface_arp_map_.find(itf->id()); + if (it != interface_arp_map_.end()) { + InterfaceArpInfo &intf_entry = it->second; + ArpKeySet::iterator key_it = intf_entry.arp_key_list.begin(); + while (key_it != intf_entry.arp_key_list.end()) { + ArpKey key = *key_it; + ++key_it; + ArpIterator arp_it = arp_cache_.find(key); + if (arp_it != arp_cache_.end()) { + ArpEntry *arp_entry = arp_it->second; + if (arp_entry->DeleteArpRoute()) { + DeleteArpEntry(arp_it); + } + } + } + intf_entry.arp_key_list.clear(); + interface_arp_map_.erase(it); + } if (itf->type() == Interface::PHYSICAL && itf->name() == agent_->fabric_interface_name()) { - for (ArpProto::ArpIterator it = arp_cache_.begin(); - it != arp_cache_.end();) { - ArpEntry *arp_entry = it->second; - if (arp_entry->DeleteArpRoute()) { - it = DeleteArpEntry(it); - } else - it++; - } set_ip_fabric_interface(NULL); set_ip_fabric_interface_index(-1); } @@ -285,6 +361,53 @@ void ArpProto::InterfaceNotify(DBEntryBase *entry) { } } +ArpProto::InterfaceArpInfo& ArpProto::ArpMapIndexToEntry(uint32_t idx) { + InterfaceArpMap::iterator it = interface_arp_map_.find(idx); + if (it == interface_arp_map_.end()) { + InterfaceArpInfo entry; + std::pair ret; + ret = interface_arp_map_.insert(InterfaceArpPair(idx, entry)); + return ret.first->second; + } else { + return it->second; + } +} + +void ArpProto::IncrementStatsArpRequest(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + entry.stats.arp_req++; +} + +void ArpProto::IncrementStatsArpReply(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + entry.stats.arp_replies++; +} + +void ArpProto::IncrementStatsResolved(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + entry.stats.resolved++; +} + +uint32_t ArpProto::ArpRequestStatsCounter(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + return entry.stats.arp_req; +} + +uint32_t ArpProto::ArpReplyStatsCounter(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + return entry.stats.arp_replies; +} + +uint32_t ArpProto::ArpResolvedStatsCounter(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + return entry.stats.resolved; +} + +void ArpProto::ClearInterfaceArpStats(uint32_t idx) { + InterfaceArpInfo &entry = ArpMapIndexToEntry(idx); + entry.stats.Reset(); +} + void ArpProto::NextHopNotify(DBEntryBase *entry) { NextHop *nh = static_cast(entry); @@ -293,10 +416,10 @@ void ArpProto::NextHopNotify(DBEntryBase *entry) { ArpNH *arp_nh = (static_cast(nh)); if (arp_nh->IsDeleted()) { SendArpIpc(ArpProto::ARP_DELETE, arp_nh->GetIp()->to_ulong(), - arp_nh->GetVrf()); + arp_nh->GetVrf(), arp_nh->GetInterface()); } else if (arp_nh->IsValid() == false) { SendArpIpc(ArpProto::ARP_RESOLVE, arp_nh->GetIp()->to_ulong(), - arp_nh->GetVrf()); + arp_nh->GetVrf(), arp_nh->GetInterface()); } break; } @@ -306,9 +429,10 @@ void ArpProto::NextHopNotify(DBEntryBase *entry) { } } -bool ArpProto::TimerExpiry(ArpKey &key, uint32_t timer_type) { +bool ArpProto::TimerExpiry(ArpKey &key, uint32_t timer_type, + const Interface* itf) { if (arp_cache_.find(key) != arp_cache_.end()) - SendArpIpc((ArpProto::ArpMsgType)timer_type, key); + SendArpIpc((ArpProto::ArpMsgType)timer_type, key, itf); return false; } @@ -327,19 +451,34 @@ void ArpProto::del_gratuitous_arp_entry() { } } -void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, - in_addr_t ip, const VrfEntry *vrf) { - ArpIpc *ipc = new ArpIpc(type, ip, vrf); +void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, in_addr_t ip, + const VrfEntry *vrf, const Interface* itf) { + ArpIpc *ipc = new ArpIpc(type, ip, vrf, itf); agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc); } -void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key) { - ArpIpc *ipc = new ArpIpc(type, key); +void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key, + const Interface* itf) { + ArpIpc *ipc = new ArpIpc(type, key, itf); agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc); } bool ArpProto::AddArpEntry(ArpEntry *entry) { - return arp_cache_.insert(ArpCachePair(entry->key(), entry)).second; + bool ret = arp_cache_.insert(ArpCachePair(entry->key(), entry)).second; + uint32_t intf_id = entry->interface()->id(); + InterfaceArpMap::iterator it = interface_arp_map_.find(intf_id); + if (it == interface_arp_map_.end()) { + InterfaceArpInfo intf_entry; + intf_entry.arp_key_list.insert(entry->key()); + interface_arp_map_.insert(InterfaceArpPair(intf_id, intf_entry)); + } else { + InterfaceArpInfo &intf_entry = it->second; + ArpKeySet::iterator key_it = intf_entry.arp_key_list.find(entry->key()); + if (key_it == intf_entry.arp_key_list.end()) { + intf_entry.arp_key_list.insert(entry->key()); + } + } + return ret; } bool ArpProto::DeleteArpEntry(ArpEntry *entry) { @@ -389,3 +528,13 @@ void ArpProto::ValidateAndClearVrfState(VrfEntry *vrf) { vrf_table_listener_id_); } } + +ArpProto::ArpIterator +ArpProto::FindUpperBoundArpEntry(const ArpKey &key) { + return arp_cache_.upper_bound(key); +} + +ArpProto::ArpIterator +ArpProto::FindLowerBoundArpEntry(const ArpKey &key) { + return arp_cache_.lower_bound(key); +} diff --git a/src/vnsw/agent/services/arp_proto.h b/src/vnsw/agent/services/arp_proto.h index 00ce186f8b2..b86957cbddb 100644 --- a/src/vnsw/agent/services/arp_proto.h +++ b/src/vnsw/agent/services/arp_proto.h @@ -26,6 +26,7 @@ class ArpProto : public Proto { typedef std::pair ArpCachePair; typedef std::map::iterator ArpIterator; typedef boost::function Callback; + typedef std::set ArpKeySet; enum ArpMsgType { ARP_RESOLVE, @@ -37,12 +38,14 @@ class ArpProto : public Proto { }; struct ArpIpc : InterTaskMsg { - ArpIpc(ArpProto::ArpMsgType msg, ArpKey &akey) - : InterTaskMsg(msg), key(akey) {} - ArpIpc(ArpProto::ArpMsgType msg, in_addr_t ip, const VrfEntry *vrf) : - InterTaskMsg(msg), key(ip, vrf) {} + ArpIpc(ArpProto::ArpMsgType msg, ArpKey &akey, const Interface* itf) + : InterTaskMsg(msg), key(akey), interface(itf) {} + ArpIpc(ArpProto::ArpMsgType msg, in_addr_t ip, const VrfEntry *vrf, + const Interface* itf) : + InterTaskMsg(msg), key(ip, vrf), interface(itf) {} ArpKey key; + const Interface *interface; }; struct ArpStats { @@ -67,19 +70,28 @@ class ArpProto : public Proto { uint32_t vm_arp_req; }; + struct InterfaceArpInfo { + InterfaceArpInfo() : arp_key_list(), stats() {} + ArpKeySet arp_key_list; + ArpStats stats; + }; + typedef std::map InterfaceArpMap; + typedef std::pair InterfaceArpPair; + void Shutdown(); ArpProto(Agent *agent, boost::asio::io_service &io, bool run_with_vrouter); virtual ~ArpProto(); ProtoHandler *AllocProtoHandler(boost::shared_ptr info, boost::asio::io_service &io); - bool TimerExpiry(ArpKey &key, uint32_t timer_type); + bool TimerExpiry(ArpKey &key, uint32_t timer_type, const Interface *itf); bool AddArpEntry(ArpEntry *entry); bool DeleteArpEntry(ArpEntry *entry); ArpEntry *FindArpEntry(const ArpKey &key); std::size_t GetArpCacheSize() { return arp_cache_.size(); } const ArpCache& arp_cache() { return arp_cache_; } + const InterfaceArpMap& interface_arp_map() { return interface_arp_map_; } Interface *ip_fabric_interface() const { return ip_fabric_interface_; } uint16_t ip_fabric_interface_index() const { @@ -126,22 +138,34 @@ class ArpProto : public Proto { const ArpStats &GetStats() const { return arp_stats_; } void ClearStats() { arp_stats_.Reset(); } + void IncrementStatsArpRequest(uint32_t idx); + void IncrementStatsArpReply(uint32_t idx); + void IncrementStatsResolved(uint32_t idx); + InterfaceArpInfo& ArpMapIndexToEntry(uint32_t idx); + uint32_t ArpRequestStatsCounter(uint32_t idx); + uint32_t ArpReplyStatsCounter(uint32_t idx); + uint32_t ArpResolvedStatsCounter(uint32_t idx); + void ClearInterfaceArpStats(uint32_t idx); + uint16_t max_retries() const { return max_retries_; } uint32_t retry_timeout() const { return retry_timeout_; } uint32_t aging_timeout() const { return aging_timeout_; } void set_max_retries(uint16_t retries) { max_retries_ = retries; } void set_retry_timeout(uint32_t timeout) { retry_timeout_ = timeout; } void set_aging_timeout(uint32_t timeout) { aging_timeout_ = timeout; } - void SendArpIpc(ArpProto::ArpMsgType type, - in_addr_t ip, const VrfEntry *vrf); + void SendArpIpc(ArpProto::ArpMsgType type, in_addr_t ip, + const VrfEntry *vrf, const Interface* itf); void ValidateAndClearVrfState(VrfEntry *vrf); + ArpIterator FindUpperBoundArpEntry(const ArpKey &key); + ArpIterator FindLowerBoundArpEntry(const ArpKey &key); private: void VrfNotify(DBTablePartBase *part, DBEntryBase *entry); void NextHopNotify(DBEntryBase *entry); void InterfaceNotify(DBEntryBase *entry); void RouteUpdate(DBTablePartBase *part, DBEntryBase *entry); - void SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key); + void SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key, + const Interface* itf); ArpProto::ArpIterator DeleteArpEntry(ArpProto::ArpIterator iter); ArpCache arp_cache_; @@ -155,6 +179,7 @@ class ArpProto : public Proto { DBTableBase::ListenerId interface_table_listener_id_; DBTableBase::ListenerId nexthop_table_listener_id_; std::map route_table_listener_; + InterfaceArpMap interface_arp_map_; uint16_t max_retries_; uint32_t retry_timeout_; // milli seconds @@ -191,18 +216,26 @@ class ArpDBState : public DBState { typedef std::map WaitForTrafficIntfMap; ArpDBState(ArpVrfState *vrf_state, uint32_t vrf_id, - IpAddress vm_ip_addr); + IpAddress vm_ip_addr, uint8_t plen); ~ArpDBState(); bool SendArpRequest(); void SendArpRequestForAllIntf(const InetUnicastRouteEntry *route); void StartTimer(); + void Update(const InetUnicastRouteEntry *route); + void UpdateArpRoutes(const InetUnicastRouteEntry *route); + void Delete(const InetUnicastRouteEntry *rt); private: ArpVrfState *vrf_state_; Timer *arp_req_timer_; uint32_t vrf_id_; IpAddress vm_ip_; + uint8_t plen_; IpAddress gw_ip_; + SecurityGroupList sg_list_; + bool policy_; + bool resolve_route_; + std::string vn_; WaitForTrafficIntfMap wait_for_traffic_map_; }; #endif // vnsw_agent_arp_proto_hpp diff --git a/src/vnsw/agent/services/services.sandesh b/src/vnsw/agent/services/services.sandesh index c52ad8a51d3..0e25da01aee 100644 --- a/src/vnsw/agent/services/services.sandesh +++ b/src/vnsw/agent/services/services.sandesh @@ -36,11 +36,26 @@ request sandesh ShowAllInfo { request sandesh ClearAllInfo { } +struct InterfaceArpStats { + 1: u32 interface_index; + 2: u32 arp_requests; + 3: u32 arp_replies; + 4: u32 arp_resolved; +} + +request sandesh InterfaceArpStatsReq { + 1: i32 interface_index = -1; +} + request sandesh PktTraceInfo { 1: u32 num_buffers = 16; 2: u32 flow_num_buffers = 16; } +response sandesh InterfaceArpStatsResponse { + 1: list stats_list; +} + response sandesh PktStats { 1: i32 total_rcvd; 2: i32 dhcp_rcvd; diff --git a/src/vnsw/agent/services/services_sandesh.cc b/src/vnsw/agent/services/services_sandesh.cc index 37bcdafb539..84af64876c2 100644 --- a/src/vnsw/agent/services/services_sandesh.cc +++ b/src/vnsw/agent/services/services_sandesh.cc @@ -1088,3 +1088,38 @@ bool ArpSandesh::SetArpEntry(const ArpKey &key, const ArpEntry *entry) { } return true; } + +void ArpSandesh::SetInterfaceArpStatsEntry( + ArpProto::InterfaceArpMap::const_iterator &it, + std::vector &list) { + InterfaceArpStats data; + data.set_interface_index(it->first); + data.set_arp_requests(it->second.stats.arp_req); + data.set_arp_replies(it->second.stats.arp_replies); + data.set_arp_resolved(it->second.stats.resolved); + list.push_back(data); +} + +void InterfaceArpStatsReq::HandleRequest() const { + InterfaceArpStatsResponse *resp = new InterfaceArpStatsResponse(); + resp->set_context(context()); + ArpSandesh arp_sandesh(resp); + const ArpProto::InterfaceArpMap &imap = + (Agent::GetInstance()->GetArpProto()->interface_arp_map()); + std::vector &list = + const_cast&>(resp->get_stats_list()); + if (get_interface_index() != -1) { + ArpProto::InterfaceArpMap::const_iterator it = imap.find + (get_interface_index()); + if (it != imap.end()) { + arp_sandesh.SetInterfaceArpStatsEntry(it, list); + } + arp_sandesh.Response(); + return; + } + for (ArpProto::InterfaceArpMap::const_iterator it = imap.begin(); + it != imap.end(); it++) { + arp_sandesh.SetInterfaceArpStatsEntry(it, list); + } + arp_sandesh.Response(); +} diff --git a/src/vnsw/agent/services/services_sandesh.h b/src/vnsw/agent/services/services_sandesh.h index aacd78d3de6..da1f3955e8e 100644 --- a/src/vnsw/agent/services/services_sandesh.h +++ b/src/vnsw/agent/services/services_sandesh.h @@ -76,6 +76,9 @@ class ArpSandesh { ArpSandesh(SandeshResponse *resp) : iter_(0), resp_(resp) {}; bool SetArpEntry(const ArpKey &key, const ArpEntry *entry); void Response() { resp_->Response(); } + void SetInterfaceArpStatsEntry( + ArpProto::InterfaceArpMap::const_iterator &it, + std::vector &list); private: int iter_; diff --git a/src/vnsw/agent/services/test/arp_test.cc b/src/vnsw/agent/services/test/arp_test.cc index 9f621a869b5..7e2b4968df5 100644 --- a/src/vnsw/agent/services/test/arp_test.cc +++ b/src/vnsw/agent/services/test/arp_test.cc @@ -162,16 +162,19 @@ class ArpTest : public ::testing::Test { } void SendArpMessage(ArpProto::ArpMsgType type, uint32_t addr) { + PhysicalInterfaceKey key(Agent::GetInstance()->fabric_interface_name()); + Interface *eth = static_cast + (Agent::GetInstance()->interface_table()->FindActiveEntry(&key)); ArpProto::ArpIpc *ipc = new ArpProto::ArpIpc(type, addr, Agent::GetInstance()->vrf_table()-> - FindVrfFromName(Agent::GetInstance()->fabric_vrf_name())); + FindVrfFromName(Agent::GetInstance()->fabric_vrf_name()), eth); Agent::GetInstance()->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc); } bool FindArpNHEntry(uint32_t addr, const string &vrf_name, bool validate = false) { Ip4Address ip(addr); - ArpNHKey key(vrf_name, ip); + ArpNHKey key(vrf_name, ip, false); ArpNH *arp_nh = static_cast(Agent::GetInstance()-> nexthop_table()-> FindActiveEntry(&key)); @@ -201,10 +204,12 @@ class ArpTest : public ::testing::Test { void ArpNHUpdate(DBRequest::DBOperation op, in_addr_t addr) { Ip4Address ip(addr); - InetUnicastAgentRouteTable::ArpRoute(op, ip, MacAddress(), + InetUnicastAgentRouteTable::ArpRoute(op, + Agent::GetInstance()->fabric_vrf_name(), + ip, MacAddress(), Agent::GetInstance()->fabric_vrf_name(), *Agent::GetInstance()->GetArpProto()->ip_fabric_interface(), - false, 32); + false, 32, false, "", SecurityGroupList()); } void TunnelNH(DBRequest::DBOperation op, uint32_t saddr, uint32_t daddr) { @@ -513,7 +518,7 @@ TEST_F(ArpTest, ArpItfDeleteTest) { WAIT_FOR(500, 1000, (VrfFind("vrf2") == false)); } #endif - +#if 0 //Test to verify sending of ARP request on new interface addition TEST_F(ArpTest, ArpReqOnVmInterface) { Agent *agent = Agent::GetInstance(); @@ -638,8 +643,291 @@ TEST_F(ArpTest, ArpReqOnVmInterface_2) { WAIT_FOR(500, 1000, (agent->vn_table()->Size() == 0)); WAIT_FOR(500, 1000, (VrfFind("vrf1") == false)); } +#endif + +//Test to check update on resolve route, would result +//in arp routes also getting updated +TEST_F(ArpTest, SubnetResolveWithoutPolicy) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + CreateVmportWithEcmp(input1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + Ip4Address sip = Ip4Address::from_string("8.1.1.1"); + Ip4Address dip = Ip4Address::from_string("8.1.1.2"); + VmInterface *vintf = VmInterfaceGet(8); + SendArpReq(vintf->id(), vintf->vrf()->vrf_id(), sip.to_ulong(), dip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == true); + + AgentRoute *rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + const ArpNH *arp_nh = static_cast(rt->GetActiveNextHop()); + EXPECT_TRUE(arp_nh->GetInterface() == vintf); + EXPECT_TRUE(arp_nh->PolicyEnabled() == false); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + DeleteVmportEnv(input1, 1, true); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + +//Test to check update on resolve route, would result +//in arp routes also getting updated +TEST_F(ArpTest, SubnetResolveWithPolicy) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + //Create VM interface with policy + CreateVmportWithEcmp(input1, 1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + Ip4Address sip = Ip4Address::from_string("8.1.1.1"); + Ip4Address dip = Ip4Address::from_string("8.1.1.2"); + VmInterface *vintf = VmInterfaceGet(8); + SendArpReq(vintf->id(), vintf->vrf()->vrf_id(), sip.to_ulong(), dip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == true); + + AgentRoute *rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + const ArpNH *arp_nh = static_cast(rt->GetActiveNextHop()); + EXPECT_TRUE(arp_nh->GetInterface() == vintf); + EXPECT_TRUE(arp_nh->PolicyEnabled() == true); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + DeleteVmportEnv(input1, 1, true, 1); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + +//Verify that ARP route gets updated with policy +//when interface policy changes +TEST_F(ArpTest, SubnetResolveWithPolicyUpdate) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + //Create VM interface with policy + CreateVmportWithEcmp(input1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + Ip4Address sip = Ip4Address::from_string("8.1.1.1"); + Ip4Address dip = Ip4Address::from_string("8.1.1.2"); + VmInterface *vintf = VmInterfaceGet(8); + SendArpReq(vintf->id(), vintf->vrf()->vrf_id(), sip.to_ulong(), dip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == true); + + AgentRoute *rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + const ArpNH *arp_nh = static_cast(rt->GetActiveNextHop()); + EXPECT_TRUE(arp_nh->GetInterface() == vintf); + EXPECT_TRUE(arp_nh->PolicyEnabled() == false); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + + SendArpReply(vintf->id(), vintf->vrf()->vrf_id(), + sip.to_ulong(), dip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, arp_nh->GetResolveState() == true); + EXPECT_TRUE(arp_nh->PolicyEnabled() == false); + + //Change policy of interface + AddAcl("acl1", 1); + AddLink("virtual-network", "vn1", "access-control-list", "acl1"); + client->WaitForIdle(); + arp_nh = static_cast(rt->GetActiveNextHop()); + EXPECT_TRUE(arp_nh->PolicyEnabled() == true); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + + DelAcl("acl1"); + DelLink("virtual-network", "vn1", "access-control-list", "acl1"); + DeleteVmportEnv(input1, 1, true); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + +//Test to check update on resolve route, would result +//in arp routes also getting updated +TEST_F(ArpTest, SubnetResolveWithSg) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + client->Reset(); + //Create VM interface with policy + CreateVmportWithEcmp(input1, 1, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + AddSg("sg1", 1); + AddAcl("acl1", 1); + AddLink("security-group", "sg1", "access-control-list", "acl1"); + client->WaitForIdle(); + AddLink("virtual-machine-interface", "vnet8", "security-group", "sg1"); + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + Ip4Address sip = Ip4Address::from_string("8.1.1.1"); + Ip4Address dip = Ip4Address::from_string("8.1.1.2"); + VmInterface *vintf = VmInterfaceGet(8); + SendArpReq(vintf->id(), vintf->vrf()->vrf_id(), sip.to_ulong(), dip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == true); + + AgentRoute *rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + const ArpNH *arp_nh = static_cast(rt->GetActiveNextHop()); + EXPECT_TRUE(arp_nh->GetInterface() == vintf); + EXPECT_TRUE(arp_nh->PolicyEnabled() == true); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + DelLink("security-group", "sg1", "access-control-list", "acl1"); + DelAcl("acl1"); + DelNode("security-group", "sg1"); + client->WaitForIdle(); + DeleteVmportEnv(input1, 1, true, 1); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + + EXPECT_FALSE(VmPortFind(8)); + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), ""); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + +TEST_F(ArpTest, IntfArpReqTest_1) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + //Create VM, VN, VRF and Vmport + CreateVmportEnv(input, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input, 0)); + Interface *itf = VmPortGet(1); + VmInterface *vmi = static_cast(itf); + VrfEntry *vrf = VrfGet("vrf1"); + + Agent::GetInstance()->GetArpProto()->ClearInterfaceArpStats(vmi->id()); + Ip4Address arp_tip = Ip4Address::from_string("1.1.1.2"); + EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize()); // For GW + SendArpReq(vmi->id(), vrf->vrf_id(), vmi->ip_addr().to_ulong(), arp_tip.to_ulong()); + WaitForCompletion(2); + EXPECT_TRUE(FindArpNHEntry(arp_tip.to_ulong(), "vrf1")); + WAIT_FOR(500, 1000, (Agent::GetInstance()->GetArpProto()->ArpRequestStatsCounter(vmi->id()) >= 1U)); + + DeleteVmportEnv(input, 1, true); + client->WaitForIdle(); +} + +TEST_F(ArpTest, IntfArpReqTest_2) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + //Create VM, VN, VRF and Vmport + CreateVmportEnv(input, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input, 0)); + Interface *itf = VmPortGet(1); + VmInterface *vmi = static_cast(itf); + VrfEntry *vrf = VrfGet("vrf1"); + + Agent::GetInstance()->GetArpProto()->ClearInterfaceArpStats(vmi->id()); + Ip4Address arp_tip = Ip4Address::from_string("1.1.1.2"); + EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize()); // For GW + SendArpReq(vmi->id(), vrf->vrf_id(), vmi->ip_addr().to_ulong(), arp_tip.to_ulong()); + WaitForCompletion(2); + EXPECT_TRUE(FindArpNHEntry(arp_tip.to_ulong(), "vrf1")); + EXPECT_TRUE(FindArpRoute(arp_tip.to_ulong(), "vrf1")); + WAIT_FOR(500, 1000, (Agent::GetInstance()->GetArpProto()->ArpRequestStatsCounter(vmi->id()) >= 1U)); + SendArpReply(vmi->id(), vrf->vrf_id(), vmi->ip_addr().to_ulong(), arp_tip.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, (1U == Agent::GetInstance()->GetArpProto()->ArpReplyStatsCounter(vmi->id()))); + WAIT_FOR(500, 1000, (1U == Agent::GetInstance()->GetArpProto()->ArpResolvedStatsCounter(vmi->id()))); + DeleteVmportEnv(input, 1, true); + client->WaitForIdle(); +} void RouterIdDepInit(Agent *agent) { } diff --git a/src/vnsw/agent/test/test_agent_route_walker.cc b/src/vnsw/agent/test/test_agent_route_walker.cc index 0b83936f6f7..27fb6bca305 100644 --- a/src/vnsw/agent/test/test_agent_route_walker.cc +++ b/src/vnsw/agent/test/test_agent_route_walker.cc @@ -78,8 +78,12 @@ class AgentRouteWalkerTest : public AgentRouteWalker, public ::testing::Test { if (num_vrfs > 2) { VrfAddReq(vrf_name_3_.c_str()); } + InetInterfaceKey vhost_intf_key( + Agent::GetInstance()->vhost_interface()->name()); Agent::GetInstance()->fabric_inet4_unicast_table()->AddResolveRoute( - Agent::GetInstance()->fabric_vrf_name(), server_ip_, 24); + Agent::GetInstance()->local_peer(), + Agent::GetInstance()->fabric_vrf_name(), server_ip_, 24, + vhost_intf_key, 0, false, "", SecurityGroupList()); client->WaitForIdle(); client->WaitForIdle(); if (num_vrfs > 0) { diff --git a/src/vnsw/agent/test/test_cmn_util.h b/src/vnsw/agent/test/test_cmn_util.h index 1b0b3e2cd6c..8ef280dbb40 100644 --- a/src/vnsw/agent/test/test_cmn_util.h +++ b/src/vnsw/agent/test/test_cmn_util.h @@ -299,6 +299,7 @@ void DelVmPortVrf(const char *name); uint32_t PathCount(const string vrf_name, const Ip4Address &addr, int plen); bool VlanNhFind(int id, uint16_t tag); void AddInstanceIp(const char *name, int id, const char* addr); +void AddSubnetType(const char *name, int id, const char* addr, uint8_t); void AddActiveActiveInstanceIp(const char *name, int id, const char* addr); void DelInstanceIp(const char *name); extern Peer *bgp_peer_; diff --git a/src/vnsw/agent/test/test_l2route.cc b/src/vnsw/agent/test/test_l2route.cc index 8ed70995e70..7ef3487aa61 100644 --- a/src/vnsw/agent/test/test_l2route.cc +++ b/src/vnsw/agent/test/test_l2route.cc @@ -118,8 +118,11 @@ class RouteTest : public ::testing::Test { } void AddResolveRoute(const Ip4Address &server_ip, uint32_t plen) { + InetInterfaceKey vhost_key(agent_->vhost_interface()->name()); agent_->fabric_inet4_unicast_table()->AddResolveRoute( - agent_->fabric_vrf_name(), server_ip, plen); + agent_->local_peer(), + agent_->fabric_vrf_name(), server_ip, plen, vhost_key, + 0, false, "", SecurityGroupList()); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_nh.cc b/src/vnsw/agent/test/test_nh.cc index f59031ecd20..44498fd62df 100644 --- a/src/vnsw/agent/test/test_nh.cc +++ b/src/vnsw/agent/test/test_nh.cc @@ -370,7 +370,7 @@ TEST_F(CfgTest, EcmpNH_2) { {"vnet5", 5, "1.1.1.1", "00:00:00:02:02:05", 1, 5} }; - CreateVmportWithEcmp(input1, 1); + CreateVmportWithEcmp(input1, 1, 1); client->WaitForIdle(); //First VM added, route points to composite NH Ip4Address ip = Ip4Address::from_string("1.1.1.1"); @@ -378,6 +378,7 @@ TEST_F(CfgTest, EcmpNH_2) { EXPECT_TRUE(rt != NULL); const NextHop *nh = rt->GetActiveNextHop(); EXPECT_TRUE(nh->GetType() == NextHop::INTERFACE); + EXPECT_TRUE(nh->PolicyEnabled() == true); //Second VM added, route should point to composite NH CreateVmportWithEcmp(input2, 1); @@ -386,6 +387,7 @@ TEST_F(CfgTest, EcmpNH_2) { EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE); const CompositeNH *comp_nh = static_cast(nh); EXPECT_TRUE(comp_nh->ComponentNHCount() == 2); + EXPECT_TRUE(comp_nh->Get(0)->nh()->PolicyEnabled() == false); CreateVmportWithEcmp(input3, 1); client->WaitForIdle(); @@ -1914,11 +1916,13 @@ TEST_F(CfgTest, Nexthop_keys) { vrf_nh->SetKey(vrf_nh_key); DoNextHopSandesh(); + InetInterfaceKey vhost_intf_key(agent_->vhost_interface()->name()); //Tunnel NH key agent_-> fabric_inet4_unicast_table()-> - AddResolveRoute(agent_->fabric_vrf_name(), - Ip4Address::from_string("10.1.1.100"), 32); + AddResolveRoute(agent_->local_peer(), agent_->fabric_vrf_name(), + Ip4Address::from_string("10.1.1.100"), 32, + vhost_intf_key, 0, false, "", SecurityGroupList()); client->WaitForIdle(); MacAddress remote_vm_mac("00:00:01:01:01:11"); @@ -2018,14 +2022,16 @@ TEST_F(CfgTest, Nexthop_keys) { //ARP NH with vm interface DBRequest arp_nh_req; arp_nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - arp_nh_req.key.reset(new ArpNHKey("vrf10", Ip4Address::from_string("11.11.11.11"))); + arp_nh_req.key.reset(new ArpNHKey("vrf10", Ip4Address::from_string("11.11.11.11"), + false)); MacAddress intf_vm_mac("00:00:01:01:01:11"); VmInterfaceKey *intf_key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, MakeUuid(10), "vrf10"); arp_nh_req.data.reset(new ArpNHData(intf_vm_mac, intf_key, true)); agent_->nexthop_table()->Enqueue(&arp_nh_req); client->WaitForIdle(); - ArpNHKey find_arp_nh_key("vrf10", Ip4Address::from_string("11.11.11.11")); + ArpNHKey find_arp_nh_key("vrf10", Ip4Address::from_string("11.11.11.11"), + false); ArpNH *arp_nh = static_cast (agent_->nexthop_table()->FindActiveEntry(&find_arp_nh_key)); EXPECT_TRUE(arp_nh != NULL); @@ -2035,11 +2041,13 @@ TEST_F(CfgTest, Nexthop_keys) { DBRequest del_arp_nh_req; del_arp_nh_req.oper = DBRequest::DB_ENTRY_DELETE; - del_arp_nh_req.key.reset(new ArpNHKey("vrf10", Ip4Address::from_string("11.11.11.11"))); - del_arp_nh_req.data.reset(new ArpNHData()); + del_arp_nh_req.key.reset(new ArpNHKey("vrf10", Ip4Address::from_string("11.11.11.11"), + false)); + del_arp_nh_req.data.reset(NULL); agent_->nexthop_table()->Enqueue(&del_arp_nh_req); client->WaitForIdle(); - ArpNHKey find_del_arp_nh_key("vrf10", Ip4Address::from_string("11.11.11.11")); + ArpNHKey find_del_arp_nh_key("vrf10", Ip4Address::from_string("11.11.11.11"), + false); EXPECT_TRUE(agent_->nexthop_table()-> FindActiveEntry(&find_del_arp_nh_key) == NULL); @@ -2061,14 +2069,17 @@ TEST_F(CfgTest, Nexthop_invalid_vrf) { client->WaitForIdle(); client->Reset(); + InetInterfaceKey vhost_intf_key(agent_->vhost_interface()->name()); //ARP NH DBRequest arp_nh_req; arp_nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - arp_nh_req.key.reset(new ArpNHKey("vrf11", Ip4Address::from_string("11.11.11.11"))); - arp_nh_req.data.reset(new ArpNHData()); + arp_nh_req.key.reset(new ArpNHKey("vrf11", Ip4Address::from_string("11.11.11.11"), + false)); + arp_nh_req.data.reset(new ArpNHData(&vhost_intf_key)); agent_->nexthop_table()->Enqueue(&arp_nh_req); client->WaitForIdle(); - ArpNHKey find_arp_nh_key("vrf11", Ip4Address::from_string("11.11.11.11")); + ArpNHKey find_arp_nh_key("vrf11", Ip4Address::from_string("11.11.11.11"), + false); EXPECT_TRUE(agent_->nexthop_table()-> FindActiveEntry(&find_arp_nh_key) == NULL); diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index 35524e8d76d..524129a51bf 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -161,8 +161,12 @@ class RouteTest : public ::testing::Test { } void AddResolveRoute(const Ip4Address &server_ip, uint32_t plen) { + InetInterfaceKey vhost_intf_key( + Agent::GetInstance()->vhost_interface()->name()); Agent::GetInstance()->fabric_inet4_unicast_table()->AddResolveRoute( - Agent::GetInstance()->fabric_vrf_name(), server_ip, plen); + Agent::GetInstance()->local_peer(), + Agent::GetInstance()->fabric_vrf_name(), server_ip, plen, + vhost_intf_key, 0, false, "", SecurityGroupList()); client->WaitForIdle(); } @@ -170,7 +174,9 @@ class RouteTest : public ::testing::Test { const Ip4Address &ip, int plen, const Ip4Address &server) { Agent::GetInstance()->fabric_inet4_unicast_table()->AddGatewayRouteReq - (vrf_name, ip, plen, server, ""); + (Agent::GetInstance()->local_peer(), + vrf_name, ip, plen, server, "", MplsTable::kInvalidLabel, + SecurityGroupList()); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_tunnel_encap.cc b/src/vnsw/agent/test/test_tunnel_encap.cc index 8b7026909d1..e705874749c 100644 --- a/src/vnsw/agent/test/test_tunnel_encap.cc +++ b/src/vnsw/agent/test/test_tunnel_encap.cc @@ -113,9 +113,13 @@ class TunnelEncapTest : public ::testing::Test { } void AddResolveRoute(const Ip4Address &server_ip, uint32_t plen) { + InetInterfaceKey vhost_intf_key( + Agent::GetInstance()->vhost_interface()->name()); Agent::GetInstance()-> fabric_inet4_unicast_table()->AddResolveRoute( - Agent::GetInstance()->fabric_vrf_name(), server_ip, plen); + Agent::GetInstance()->local_peer(), + Agent::GetInstance()->fabric_vrf_name(), server_ip, plen, + vhost_intf_key, 0, false, "", SecurityGroupList()); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 65998d76904..f551e6431e7 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -1268,9 +1268,10 @@ bool AddArp(const char *ip, const char *mac_str, const char *ifname) { intf = static_cast(Agent::GetInstance()->interface_table()->FindActiveEntry(&key)); boost::system::error_code ec; InetUnicastAgentRouteTable::ArpRoute(DBRequest::DB_ENTRY_ADD_CHANGE, + Agent::GetInstance()->fabric_vrf_name(), Ip4Address::from_string(ip, ec), mac, Agent::GetInstance()->fabric_vrf_name(), - *intf, true, 32); + *intf, true, 32, false, "", SecurityGroupList()); return true; } @@ -1282,8 +1283,10 @@ bool DelArp(const string &ip, const char *mac_str, const string &ifname) { intf = static_cast(Agent::GetInstance()->interface_table()->FindActiveEntry(&key)); boost::system::error_code ec; InetUnicastAgentRouteTable::ArpRoute(DBRequest::DB_ENTRY_DELETE, + Agent::GetInstance()->fabric_vrf_name(), Ip4Address::from_string(ip, ec), - mac, Agent::GetInstance()->fabric_vrf_name(), *intf, false, 32); + mac, Agent::GetInstance()->fabric_vrf_name(), *intf, + false, 32, false, "", SecurityGroupList()); return true; } @@ -1566,6 +1569,16 @@ void DelInstanceIp(const char *name) { DelNode("instance-ip", name); } +void AddSubnetType(const char *name, int id, const char *addr, uint8_t plen) { + + char buf[1024]; + sprintf(buf, "\n" + "%s\n" + "%d\n" + "", addr, plen); + AddNode("subnet", name, id, buf); +} + void AddVmPortVrf(const char *name, const string &ip, uint16_t tag) { char buff[256]; int len = 0; From 2a8042bde6446411e41e994b3ff10f561c580603 Mon Sep 17 00:00:00 2001 From: Ashok Singh Date: Thu, 30 Oct 2014 02:46:14 -0700 Subject: [PATCH 186/218] Add new VM interface subtype for VCPE and make this interface active even when there is no IP Address assigned to it. --- src/vnsw/agent/oper/interface.cc | 5 +++++ src/vnsw/agent/oper/vm_interface.cc | 22 +++++++++++++++++++--- src/vnsw/agent/oper/vm_interface.h | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 0c1cee3d406..57ae1a22046 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -671,6 +671,11 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { common_reason += "vrf-null "; } + if (vintf->subnet().is_unspecified() && + vintf->os_index() == Interface::kInvalidIndex) { + common_reason += "no-dev "; + } + if (vintf->NeedDevice()) { if (vintf->os_index() == Interface::kInvalidIndex) { common_reason += "no-dev "; diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 400c5c6c6ce..60f87fa1b64 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -727,6 +727,9 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { } } + if (!data->subnet_.is_unspecified()) { + interface_sub_type = VmInterface::VCPE; + } data->sub_type_ = interface_sub_type; if (cfg->mac_addresses().size()) { data->vm_mac_ = cfg->mac_addresses().at(0); @@ -1506,6 +1509,10 @@ bool VmInterface::NeedDevice() const { if (sub_type_ == TOR) ret = false; + if (subnet_.is_unspecified() == false) { + return false; + } + if (rx_vlan_id_ != VmInterface::kInvalidVlanId) { ret = false; } else { @@ -1554,14 +1561,18 @@ bool VmInterface::IsActive() const { return true; } - if (os_index_ == kInvalidIndex) + if (subnet_.is_unspecified() && os_index_ == kInvalidIndex) return false; return mac_set_; } bool VmInterface::IsIpv4Active() const { - if (!layer3_forwarding() || (ip_addr_.to_ulong() == 0)) { + if (!layer3_forwarding()) { + return false; + } + + if (subnet_.is_unspecified() && ip_addr_.to_ulong() == 0) { return false; } @@ -1844,7 +1855,12 @@ Ip4Address VmInterface::GetGateway() const { if (vn_.get() == NULL) { return ip; } - const VnIpam *ipam = vn_->GetIpam(ip_addr_); + const VnIpam *ipam = NULL; + if (subnet_.is_unspecified()) { + ipam = vn_->GetIpam(ip_addr_); + } else { + ipam = vn_->GetIpam(subnet_); + } if (ipam) { ip = ipam->default_gw.to_v4(); } diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index 0d0ee179db5..529318f7c83 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -36,7 +36,8 @@ class VmInterface : public Interface { enum SubType { NONE, TOR, - NOVA + NOVA, + VCPE }; struct ListEntry { From 09c37758dc6c665ead8169981f1725ae33f0e3ef Mon Sep 17 00:00:00 2001 From: Ashok Singh Date: Thu, 30 Oct 2014 23:35:54 -0700 Subject: [PATCH 187/218] --Fix issue of resolve route not getting deleted when VM interface subtype changes from VCPE to TOR --Increase preference of Local VM port peer to give higher priority to resolve route --- src/vnsw/agent/oper/peer.h | 4 ++-- src/vnsw/agent/oper/vm_interface.cc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vnsw/agent/oper/peer.h b/src/vnsw/agent/oper/peer.h index 3f75a65b74c..3c3d16e3564 100644 --- a/src/vnsw/agent/oper/peer.h +++ b/src/vnsw/agent/oper/peer.h @@ -32,15 +32,15 @@ class Peer { typedef std::map PeerMap; typedef std::pair PeerPair; enum Type { - MULTICAST_PEER, BGP_PEER, LINKLOCAL_PEER, ECMP_PEER, + LOCAL_VM_PORT_PEER, LOCAL_VM_PEER, LOCAL_PEER, - LOCAL_VM_PORT_PEER, NOVA_PEER, VGW_PEER, + MULTICAST_PEER, MULTICAST_FABRIC_TREE_BUILDER, OVS_PEER, MULTICAST_TOR_PEER diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 60f87fa1b64..45dded41f39 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -996,7 +996,8 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old uint8_t old_subnet_plen) { //Need not apply config for TOR VMI as it is more of an inidicative //interface. No route addition or NH addition happens for this interface. - if (sub_type_ == VmInterface::TOR) + if (sub_type_ == VmInterface::TOR && + (old_subnet.is_unspecified() && old_subnet_plen == 0)) return; bool force_update = false; From 1a1c7ea6adbc9cc9a47b3ad162818423ae8893e4 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Thu, 30 Oct 2014 14:05:29 +0530 Subject: [PATCH 188/218] Fix wrong reporting of Active state for ToR interfaces ToR interfaces are only logical ones and do not have any corresponding device in the OS. Ignore the link-state and also presence of devices for ToR and VLAN interfaces --- src/vnsw/agent/oper/vm_interface.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 45dded41f39..a837ec5404a 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -1511,7 +1511,7 @@ bool VmInterface::NeedDevice() const { ret = false; if (subnet_.is_unspecified() == false) { - return false; + ret = false; } if (rx_vlan_id_ != VmInterface::kInvalidVlanId) { From 5605b2b35292626de6d57d83f43b1c5c1febe7e6 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Mon, 3 Nov 2014 11:28:39 +0530 Subject: [PATCH 189/218] Build physical-device-vn table based on logical-interface config In current design, physical-device-vn table was built on link between physical-router and virtual-network. This link is not expected in case of OVS. For OVS, the table should be built from - - - - --- src/vnsw/agent/oper/vm_interface.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index a837ec5404a..9187bfe1641 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -57,7 +57,8 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), - sub_type_(VmInterface::NONE), ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { + sub_type_(VmInterface::NONE), ifmap_node_(NULL), subnet_(0), + subnet_plen_(0) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -1328,6 +1329,15 @@ bool VmInterface::CopyConfig(const InterfaceTable *table, (table->agent()->interface_table()->FindActiveEntry(&key)); assert(parent_ != NULL); } + + if (ifmap_node_ != data->ifmap_node_) { + if (ifmap_node_ != NULL) + table->operdb()->dependency_manager()->ResetObject(ifmap_node_); + ifmap_node_ = data->ifmap_node_; + if (ifmap_node_) + table->operdb()->dependency_manager()->SetObject(ifmap_node_, this); + } + return ret; } From d9ce3b7692eba222fcb17a97232b570161ad0d9e Mon Sep 17 00:00:00 2001 From: Ashok Singh Date: Wed, 29 Oct 2014 10:15:57 -0700 Subject: [PATCH 190/218] Initial VCPE changes --- src/vnsw/agent/oper/vm_interface.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 9187bfe1641..91a3de51df5 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -1866,12 +1866,14 @@ Ip4Address VmInterface::GetGateway() const { if (vn_.get() == NULL) { return ip; } + const VnIpam *ipam = NULL; if (subnet_.is_unspecified()) { ipam = vn_->GetIpam(ip_addr_); } else { ipam = vn_->GetIpam(subnet_); } + if (ipam) { ip = ipam->default_gw.to_v4(); } From 4ad68fb634822687824fe162fcdf029a125406f4 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Thu, 6 Nov 2014 00:31:48 +0530 Subject: [PATCH 191/218] Enhancements to support tunnel/tap interface as physical ports Agent modifications to - support no-arp on physical/vhost interface. Agent reads the IFFLAGS from interface to find no-arp flag When interface is marked with no-arp, agent will send packets with pre-determined ethernet header - raw-ip on physical interface. Allow agent to send/receive raw-ip packets without ethernet header on physical-port. This is used when physical-interface is of type TUN --- src/vnsw/agent/init/agent_param.cc | 41 ++++++-- src/vnsw/agent/init/agent_param.h | 4 + src/vnsw/agent/init/contrail_init_common.cc | 16 ++- src/vnsw/agent/ksync/interface_ksync.cc | 39 +++++++- src/vnsw/agent/ksync/interface_ksync.h | 4 + src/vnsw/agent/ksync/nexthop_ksync.cc | 31 +++--- src/vnsw/agent/ksync/vnswif_listener_base.cc | 3 +- src/vnsw/agent/oper/agent_path.h | 19 ++++ src/vnsw/agent/oper/inet_interface.cc | 98 +++++++++++++------ src/vnsw/agent/oper/inet_unicast_route.cc | 45 +++++++++ src/vnsw/agent/oper/inet_unicast_route.h | 5 + src/vnsw/agent/oper/interface.cc | 37 ++++--- src/vnsw/agent/oper/nexthop.cc | 18 ++++ src/vnsw/agent/oper/nexthop.h | 3 + src/vnsw/agent/oper/physical_interface.h | 26 ++++- .../agent/oper/test/test_inet_interface.cc | 81 +++++++++++++++ src/vnsw/agent/oper/vm_interface.cc | 3 +- .../physical_devices/tables/physical_port.cc | 3 +- src/vnsw/agent/pkt/test/test_flowtable.cc | 3 +- src/vnsw/agent/pkt/test/test_pkt.cc | 3 +- src/vnsw/agent/pkt/test/test_pkt_flow.cc | 3 +- src/vnsw/agent/test/test_fip_cfg.cc | 3 +- src/vnsw/agent/test/test_l2route.cc | 3 +- src/vnsw/agent/test/test_mirror.cc | 3 +- src/vnsw/agent/test/test_route.cc | 3 +- src/vnsw/agent/test/test_vmport_cfg.cc | 6 +- 26 files changed, 423 insertions(+), 80 deletions(-) diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index fffc7446957..e14d349d0e7 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -735,7 +736,11 @@ void AgentParam::ComputeFlowLimits() { } } -static bool ValidateInterface(bool test_mode, const std::string &ifname) { +static bool ValidateInterface(bool test_mode, const std::string &ifname, + bool *no_arp, string *eth_encap) { + *no_arp = false; + *eth_encap = ""; + if (test_mode) { return true; } @@ -745,7 +750,7 @@ static bool ValidateInterface(bool test_mode, const std::string &ifname) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE); - int err = ioctl(fd, SIOCGIFHWADDR, (void *)&ifr); + int err = ioctl(fd, SIOCGIFFLAGS, (void *)&ifr); close (fd); if (err < 0) { @@ -754,6 +759,22 @@ static bool ValidateInterface(bool test_mode, const std::string &ifname) { return false; } + if ((ifr.ifr_flags & IFF_NOARP)) { + *no_arp = true; + } + + char fname[128]; + snprintf(fname, 128, "/sys/class/net/%s/type", ifname.c_str()); + FILE *f = fopen(fname, "r"); + if (f) { + int type; + if (fscanf(f, "%d", &type) >= 0) { + if (type == ARPHRD_NONE) { + *eth_encap = "none"; + } + } + } + return true; } @@ -764,8 +785,10 @@ int AgentParam::Validate() { return (EINVAL); } + bool no_arp; + string encap; // Check if interface is already present - if (ValidateInterface(test_mode_, vhost_.name_) == false) { + if (ValidateInterface(test_mode_, vhost_.name_, &no_arp, &encap) == false) { return (ENODEV); } @@ -776,7 +799,8 @@ int AgentParam::Validate() { } // Check if interface is already present - if (ValidateInterface(test_mode_, eth_port_) == false) { + if (ValidateInterface(test_mode_, eth_port_, ð_port_no_arp_, + ð_port_encap_type_) == false) { return (ENODEV); } @@ -788,7 +812,8 @@ int AgentParam::Validate() { return (EINVAL); } - if (ValidateInterface(test_mode_, vmware_physical_port_) == false) { + if (ValidateInterface(test_mode_, vmware_physical_port_, &no_arp, + &encap) == false) { return (ENODEV); } } @@ -824,6 +849,10 @@ void AgentParam::LogConfig() const { << "/" << vhost_.plen_); LOG(DEBUG, "vhost gateway : " << vhost_.gw_.to_string()); LOG(DEBUG, "Ethernet port : " << eth_port_); + LOG(DEBUG, "Ethernet Encap Type : " << eth_port_encap_type_); + if (eth_port_no_arp_) { + LOG(DEBUG, "Ethernet No-ARP : " << "TRUE"); + } LOG(DEBUG, "XMPP Server-1 : " << xmpp_server_1_); LOG(DEBUG, "XMPP Server-2 : " << xmpp_server_2_); LOG(DEBUG, "DNS Server-1 : " << dns_server_1_); @@ -898,7 +927,7 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, enable_hypervisor_options_(enable_hypervisor_options), enable_service_options_(enable_service_options), enable_tsn_(enable_tsn), tsn_ip_1_(), tsn_ip_2_(), - vhost_(), eth_port_(), + vhost_(), eth_port_(), eth_port_no_arp_(false), eth_port_encap_type_(), xmpp_instance_count_(), xmpp_server_1_(), xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dns_port_1_(ContrailPorts::DnsServerPort()), diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index 3573c173451..ee94f8dfccf 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -77,6 +77,8 @@ class AgentParam { const std::string &agent_name() const { return agent_name_; } const std::string ð_port() const { return eth_port_; } + const bool ð_port_no_arp() const { return eth_port_no_arp_; } + const std::string ð_port_encap_type() const { return eth_port_encap_type_; } const Ip4Address &tsn_ip_1() const { return tsn_ip_1_; } const Ip4Address &tsn_ip_2() const { return tsn_ip_2_; } const Ip4Address &xmpp_server_1() const { return xmpp_server_1_; } @@ -248,6 +250,8 @@ class AgentParam { PortInfo vhost_; std::string agent_name_; std::string eth_port_; + bool eth_port_no_arp_; + std::string eth_port_encap_type_; uint16_t xmpp_instance_count_; Ip4Address xmpp_server_1_; Ip4Address xmpp_server_2_; diff --git a/src/vnsw/agent/init/contrail_init_common.cc b/src/vnsw/agent/init/contrail_init_common.cc index 612f535a150..4ceaab3f815 100644 --- a/src/vnsw/agent/init/contrail_init_common.cc +++ b/src/vnsw/agent/init/contrail_init_common.cc @@ -117,12 +117,23 @@ void ContrailInitCommon::CreateVrf() { } } +static PhysicalInterface::EncapType ComputeEncapType(const string &encap) { + if (encap == "none") { + return PhysicalInterface::RAW_IP; + } + return PhysicalInterface::ETHERNET; +} + void ContrailInitCommon::CreateInterfaces() { InterfaceTable *table = agent()->interface_table(); + PhysicalInterface::EncapType type; + type = ComputeEncapType(agent_param()->eth_port_encap_type()); PhysicalInterface::Create(table, agent_param()->eth_port(), agent()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, type, + agent_param()->eth_port_no_arp()); + InetInterface::Create(table, agent_param()->vhost_name(), InetInterface::VHOST, agent()->fabric_vrf_name(), agent_param()->vhost_addr(), @@ -135,7 +146,8 @@ void ContrailInitCommon::CreateInterfaces() { PhysicalInterface::Create(agent()->interface_table(), agent_param()->vmware_physical_port(), agent()->fabric_vrf_name(), - PhysicalInterface::VMWARE); + PhysicalInterface::VMWARE, + PhysicalInterface::ETHERNET, false); } InetInterfaceKey key(agent()->vhost_interface_name()); diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 1b677dd3488..40d129e922b 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -65,7 +65,9 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, vrf_id_(entry->vrf_id_), persistent_(entry->persistent_), subtype_(entry->subtype_), - xconnect_(entry->xconnect_) { + xconnect_(entry->xconnect_), + no_arp_(entry->no_arp_), + encap_type_(entry->encap_type_) { } InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, @@ -98,7 +100,9 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, vrf_id_(intf->vrf_id()), persistent_(false), subtype_(PhysicalInterface::INVALID), - xconnect_(NULL) { + xconnect_(NULL), + no_arp_(false), + encap_type_(PhysicalInterface::ETHERNET) { if (intf->flow_key_nh()) { flow_key_nh_id_ = intf->flow_key_nh()->id(); @@ -125,7 +129,16 @@ InterfaceKSyncEntry::InterfaceKSyncEntry(InterfaceKSyncObject *obj, if (sub_type_ == InetInterface::VHOST) { InterfaceKSyncEntry tmp(ksync_obj_, inet_intf->xconnect()); xconnect_ = ksync_obj_->GetReference(&tmp); + InterfaceKSyncEntry *xconnect = static_cast + (xconnect_.get()); + encap_type_ = xconnect->encap_type(); + no_arp_ = xconnect->no_arp(); } + } else if (type_ == Interface::PHYSICAL) { + const PhysicalInterface *physical_intf = + static_cast(intf); + encap_type_ = physical_intf->encap_type(); + no_arp_ = physical_intf->no_arp(); } } @@ -296,9 +309,29 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { subtype_ = phy_intf->subtype(); break; } - case Interface::INET: + case Interface::INET: { dmac = intf->mac(); + + bool no_arp = false; + PhysicalInterface::EncapType encap = PhysicalInterface::ETHERNET; + InterfaceKSyncEntry *xconnect = static_cast + (xconnect_.get()); + if (xconnect) { + no_arp = xconnect->no_arp(); + encap = xconnect->encap_type(); + } + + if (no_arp_ != no_arp) { + no_arp_ = no_arp; + ret = true; + } + if (encap_type_ != encap) { + encap_type_ = encap; + ret = true; + } + break; + } default: assert(0); } diff --git a/src/vnsw/agent/ksync/interface_ksync.h b/src/vnsw/agent/ksync/interface_ksync.h index 7222e074c52..ae5a3485128 100644 --- a/src/vnsw/agent/ksync/interface_ksync.h +++ b/src/vnsw/agent/ksync/interface_ksync.h @@ -53,6 +53,8 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { uint32_t interface_id() const {return interface_id_;} const string &interface_name() const {return interface_name_;} bool has_service_vlan() const {return has_service_vlan_;} + bool no_arp() const { return no_arp_; } + PhysicalInterface::EncapType encap_type() const { return encap_type_; } KSyncDBObject *GetObject(); virtual bool Sync(DBEntry *e); @@ -96,6 +98,8 @@ class InterfaceKSyncEntry : public KSyncNetlinkDBEntry { bool persistent_; PhysicalInterface::SubType subtype_; KSyncEntryPtr xconnect_; + bool no_arp_; + PhysicalInterface::EncapType encap_type_; DISALLOW_COPY_AND_ASSIGN(InterfaceKSyncEntry); }; diff --git a/src/vnsw/agent/ksync/nexthop_ksync.cc b/src/vnsw/agent/ksync/nexthop_ksync.cc index c04009083eb..5aade68d748 100644 --- a/src/vnsw/agent/ksync/nexthop_ksync.cc +++ b/src/vnsw/agent/ksync/nexthop_ksync.cc @@ -459,18 +459,21 @@ bool NHKSyncEntry::Sync(DBEntry *e) { const TunnelNH *tun_nh = static_cast(e); const NextHop *active_nh = tun_nh->GetRt()->GetActiveNextHop(); - if (active_nh->GetType() != NextHop::ARP) { - valid_ = false; - interface_ = NULL; - dmac_.Zero(); - break; + if (active_nh->GetType() == NextHop::ARP) { + const ArpNH *arp_nh = static_cast(active_nh); + InterfaceKSyncObject *interface_object = + ksync_obj_->ksync()->interface_ksync_obj(); + InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface()); + interface_ = interface_object->GetReference(&if_ksync); + dmac_ = arp_nh->GetMac(); + } else if (active_nh->GetType() == NextHop::INTERFACE) { + const InterfaceNH *intf_nh = + static_cast(active_nh); + InterfaceKSyncObject *interface_object = + ksync_obj_->ksync()->interface_ksync_obj(); + InterfaceKSyncEntry if_ksync(interface_object, intf_nh->GetInterface()); + interface_ = interface_object->GetReference(&if_ksync); } - const ArpNH *arp_nh = static_cast(active_nh); - InterfaceKSyncObject *interface_object = - ksync_obj_->ksync()->interface_ksync_obj(); - InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface()); - interface_ = interface_object->GetReference(&if_ksync); - dmac_ = arp_nh->GetMac(); break; } @@ -630,7 +633,7 @@ int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { } encoder.set_nhr_encap_oif_id(intf_id); - SetEncap(NULL,encap); + SetEncap(if_ksync,encap); encoder.set_nhr_encap(encap); if (tunnel_type_.GetType() == TunnelType::MPLS_UDP) { flags |= NH_FLAG_TUNNEL_UDP_MPLS; @@ -958,6 +961,10 @@ void NHKSyncEntry::SetEncap(InterfaceKSyncEntry *if_ksync, return; } + if (if_ksync && if_ksync->encap_type() == PhysicalInterface::RAW_IP) { + return; + } + const MacAddress *smac = &MacAddress::ZeroMac(); /* DMAC encode */ for (size_t i = 0 ; i < dmac_.size(); i++) { diff --git a/src/vnsw/agent/ksync/vnswif_listener_base.cc b/src/vnsw/agent/ksync/vnswif_listener_base.cc index f90a08454b8..159b2ecaf76 100644 --- a/src/vnsw/agent/ksync/vnswif_listener_base.cc +++ b/src/vnsw/agent/ksync/vnswif_listener_base.cc @@ -334,7 +334,8 @@ void VnswInterfaceListenerBase::HandleAddressEvent(const Event *event) { agent_->set_vhost_prefix_len(event->plen_); InetInterface::CreateReq(agent_->interface_table(), agent_->vhost_interface_name(), - InetInterface::VHOST, agent_->fabric_vrf_name(), + InetInterface::VHOST, + agent_->fabric_vrf_name(), event->addr_, event->plen_, agent_->vhost_default_gateway(), Agent::NullString(), agent_->fabric_vrf_name()); diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index 54cd1edd949..1c6d9d70d50 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -15,6 +15,8 @@ //Forward declaration class AgentXmppChannel; +class InterfaceKey; +class PhysicalInterface; class Peer; class PathPreference { @@ -478,4 +480,21 @@ class DropRoute : public AgentRouteData { std::string vn_; DISALLOW_COPY_AND_ASSIGN(DropRoute); }; + +class Inet4UnicastInterfaceRoute : public AgentRouteData { +public: + Inet4UnicastInterfaceRoute(const PhysicalInterface *interface, + const std::string &vn_name); + virtual ~Inet4UnicastInterfaceRoute() { } + + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); + virtual std::string ToString() const {return "Interface";} + +private: + std::auto_ptr interface_key_; + std::string vn_name_; + DISALLOW_COPY_AND_ASSIGN(Inet4UnicastInterfaceRoute); +}; + #endif // vnsw_agent_path_hpp diff --git a/src/vnsw/agent/oper/inet_interface.cc b/src/vnsw/agent/oper/inet_interface.cc index 9986c06fc12..b85ac49d8bb 100644 --- a/src/vnsw/agent/oper/inet_interface.cc +++ b/src/vnsw/agent/oper/inet_interface.cc @@ -147,12 +147,24 @@ void InetInterface::DeActivateSimpleGateway() { // Add default route with given gateway static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, - const VrfEntry *vrf, const Ip4Address &gw, - const string &vn_name) { + const VrfEntry *vrf, const Interface *xconnect, + const Ip4Address &gw, const string &vn_name) { + + if (xconnect) { + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf->no_arp()) { + table->AddInterfaceRouteReq(agent, agent->local_peer(), + vrf->GetName(), Ip4Address(0), 0, + xconnect, vn_name); + return; + } + } table->AddGatewayRoute(agent->local_peer(), vrf->GetName(), Ip4Address(0), 0, gw, vn_name, MplsTable::kInvalidLabel, SecurityGroupList()); + return; } static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, @@ -166,12 +178,18 @@ static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, // - Resolve route for the subnet address static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, const VrfEntry *vrf, const string &interface, - const Ip4Address &addr, int plen, - const string &vn_name) { + const Interface *xconnect, const Ip4Address &addr, + int plen, const string &vn_name) { table->AddVHostRecvRoute(agent->local_peer(), vrf->GetName(), interface, addr, 32, vn_name, false); + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf && physical_intf->no_arp()) { + return; + } + table->AddVHostSubnetRecvRoute(agent->local_peer(), vrf->GetName(), interface, GetIp4SubnetBroadcastAddress(addr, plen), @@ -185,9 +203,15 @@ static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, } static void DeleteHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, - const VrfEntry *vrf, const Ip4Address &addr, - int plen) { + const VrfEntry *vrf, const Interface *xconnect, + const Ip4Address &addr, int plen) { table->Delete(agent->local_peer(), vrf->GetName(), addr, 32); + const PhysicalInterface *physical_intf = + static_cast(xconnect); + if (physical_intf && physical_intf->no_arp()) { + return; + } + table->Delete(agent->local_peer(), vrf->GetName(), Address::GetIp4SubnetAddress(addr, plen), plen); table->Delete(agent->local_peer(), vrf->GetName(), @@ -210,20 +234,25 @@ void InetInterface::ActivateHostInterface() { InetUnicastAgentRouteTable *uc_rt_table = (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName())); if (ip_addr_.to_ulong()) { - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); } if (gw_.to_ulong()) { - AddDefaultRoute(agent, uc_rt_table, vrf(), gw_, vn_name_); + AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_, + vn_name_); } - // Add receive-route for broadcast address - Inet4MulticastAgentRouteTable *mc_rt_table = - static_cast - (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); - mc_rt_table->AddVHostRecvRoute(vrf()->GetName(), name_, - Ip4Address(0xFFFFFFFF), false); + const PhysicalInterface *physical_intf = + static_cast(xconnect_.get()); + if (physical_intf && physical_intf->no_arp() == false) { + // Add receive-route for broadcast address + Inet4MulticastAgentRouteTable *mc_rt_table = + static_cast + (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); + mc_rt_table->AddVHostRecvRoute(vrf()->GetName(), name_, + Ip4Address(0xFFFFFFFF), false); + } ReceiveNHKey nh_key(new InetInterfaceKey(name_), false); flow_key_nh_ = static_cast( agent->nexthop_table()->FindActiveEntry(&nh_key)); @@ -237,19 +266,24 @@ void InetInterface::DeActivateHostInterface() { InetUnicastAgentRouteTable *uc_rt_table = (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName())); if (ip_addr_.to_ulong()) { - DeleteHostRoutes(agent, uc_rt_table, vrf(), ip_addr_, plen_); + DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), ip_addr_, + plen_); } if (gw_.to_ulong()) { DeleteDefaultRoute(agent, uc_rt_table, vrf(), gw_); } - Inet4MulticastAgentRouteTable *mc_rt_table = - static_cast - (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); - // Add receive-route for broadcast address - mc_rt_table->Delete(vrf()->GetName(), Ip4Address(0), - Ip4Address(0xFFFFFFFF)); + const PhysicalInterface *physical_intf = + static_cast(xconnect_.get()); + if (physical_intf && physical_intf->no_arp() == false) { + Inet4MulticastAgentRouteTable *mc_rt_table = + static_cast + (VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName())); + // Add receive-route for broadcast address + mc_rt_table->Delete(vrf()->GetName(), Ip4Address(0), + Ip4Address(0xFFFFFFFF)); + } // Delete receive nexthops ReceiveNH::Delete(agent->nexthop_table(), name_); @@ -270,7 +304,8 @@ InetInterface::InetInterface(const std::string &name, SubType sub_type, const Ip4Address &gw, Interface *xconnect, const std::string &vn_name) : Interface(Interface::INET, nil_uuid(), name, vrf), sub_type_(sub_type), - ip_addr_(ip_addr), plen_(plen), gw_(gw), xconnect_(xconnect), vn_name_(vn_name) { + ip_addr_(ip_addr), plen_(plen), gw_(gw), xconnect_(xconnect), + vn_name_(vn_name) { ipv4_active_ = false; l2_active_ = false; } @@ -343,7 +378,8 @@ bool InetInterface::OnChange(InetInterfaceData *data) { if (ip_addr_ != data->ip_addr_ || plen_ != data->plen_) { // Delete routes based on old ip-addr and prefix if (ip_addr_.to_ulong()) { - DeleteHostRoutes(agent, uc_rt_table, vrf(), ip_addr_, plen_); + DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), + ip_addr_, plen_); } ip_addr_ = data->ip_addr_; @@ -351,15 +387,15 @@ bool InetInterface::OnChange(InetInterfaceData *data) { vn_name_ = data->vn_name_; // Add routes for new ip-address and prefix if (data->ip_addr_.to_ulong()) { - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); } ret = true; } else if (vn_name_ != data->vn_name_) { // Change in vn_name, update route with new VN Name vn_name_ = data->vn_name_; - AddHostRoutes(agent, uc_rt_table, vrf(), name(), ip_addr_, plen_, - vn_name_); + AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(), + ip_addr_, plen_, vn_name_); ret = true; } @@ -372,7 +408,8 @@ bool InetInterface::OnChange(InetInterfaceData *data) { gw_ = data->gw_; // Add route for new gateway if (gw_.to_ulong()) { - AddDefaultRoute(agent, uc_rt_table, vrf(), gw_, vn_name_); + AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_, + vn_name_); } ret = true; @@ -391,7 +428,8 @@ void InetInterface::CreateReq(InterfaceTable *table, const std::string &ifname, DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new InetInterfaceKey(ifname)); req.data.reset(new InetInterfaceData(sub_type, vrf_name, Ip4Address(addr), - plen, Ip4Address(gw), xconnect, vn_name)); + plen, Ip4Address(gw), xconnect, + vn_name)); table->Enqueue(&req); } diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 2e88ab94a9a..f34839cb810 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -685,6 +685,33 @@ bool Inet4UnicastGatewayRoute::AddChangePath(Agent *agent, AgentPath *path, return true; } +Inet4UnicastInterfaceRoute::Inet4UnicastInterfaceRoute +(const PhysicalInterface *interface, const std::string &vn_name) : + AgentRouteData(false), + interface_key_(new PhysicalInterfaceKey(interface->name())), + vn_name_(vn_name) { +} + +bool Inet4UnicastInterfaceRoute::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { + bool ret = false; + + path->set_unresolved(false); + if (path->dest_vn_name() != agent->fabric_vn_name()) { + path->set_dest_vn_name(agent->fabric_vn_name()); + ret = true; + } + + InterfaceNHKey key(interface_key_->Clone(), false, InterfaceNHFlags::INET4); + NextHop *nh = static_cast + (agent->nexthop_table()->FindActiveEntry(&key)); + if (path->ChangeNH(agent, nh) == true) { + ret = true; + } + + return ret; +} + ///////////////////////////////////////////////////////////////////////////// // Sandesh functions ///////////////////////////////////////////////////////////////////////////// @@ -1346,3 +1373,21 @@ InetUnicastAgentRouteTable::AddSubnetRoute(const string &vrf_name, table->Process(req); } } + +void +InetUnicastAgentRouteTable::AddInterfaceRouteReq(Agent *agent, const Peer *peer, + const string &vrf_name, + const Ip4Address &ip, + uint8_t plen, + const Interface *interface, + const string &vn_name) { + + assert(interface->type() == Interface::PHYSICAL); + DBRequest rt_req(DBRequest::DB_ENTRY_ADD_CHANGE); + rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(), + vrf_name, ip, plen)); + const PhysicalInterface *phy_intf = static_cast + (interface); + rt_req.data.reset(new Inet4UnicastInterfaceRoute(phy_intf, vn_name)); + Inet4UnicastTableEnqueue(agent, &rt_req); +} diff --git a/src/vnsw/agent/oper/inet_unicast_route.h b/src/vnsw/agent/oper/inet_unicast_route.h index ee057610805..9fd542d208a 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.h +++ b/src/vnsw/agent/oper/inet_unicast_route.h @@ -287,6 +287,11 @@ class InetUnicastAgentRouteTable : public AgentRouteTable { void AddSubnetRoute(const string &vm_vrf, const IpAddress &addr, uint8_t plen, const string &vn_name, uint32_t vxlan_id); + void AddInterfaceRouteReq(Agent *agent, const Peer *peer, + const string &vrf_name, + const Ip4Address &ip, uint8_t plen, + const Interface *interface, + const std::string &vn_name); void AddClonedLocalPathReq(const Peer *peer, const string &vm_vrf, const IpAddress &addr, uint8_t plen, ClonedLocalPath *data); diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 57ae1a22046..90396b96be2 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -380,9 +380,10 @@ void PacketInterface::Delete(InterfaceTable *table, const std::string &ifname) { // Ethernet Interface routines ///////////////////////////////////////////////////////////////////////////// PhysicalInterface::PhysicalInterface(const std::string &name, VrfEntry *vrf, - SubType subtype) : + SubType subtype, EncapType encap, + bool no_arp) : Interface(Interface::PHYSICAL, nil_uuid(), name, vrf), - persistent_(false), subtype_(subtype) { + persistent_(false), subtype_(subtype), encap_type_(encap), no_arp_(no_arp) { if (subtype_ == VMWARE) persistent_ = true; } @@ -401,20 +402,25 @@ DBEntryBase::KeyPtr PhysicalInterface::GetDBRequestKey() const { return DBEntryBase::KeyPtr(key); } +void PhysicalInterface::Add() { +} + // Enqueue DBRequest to create a Host Interface void PhysicalInterface::CreateReq(InterfaceTable *table, const string &ifname, - const string &vrf_name, SubType subtype) { + const string &vrf_name, SubType subtype, + EncapType encap, bool no_arp) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype, encap, no_arp)); table->Enqueue(&req); } void PhysicalInterface::Create(InterfaceTable *table, const string &ifname, - const string &vrf_name, SubType subtype) { + const string &vrf_name, SubType subtype, + EncapType encap, bool no_arp) { DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new PhysicalInterfaceKey(ifname)); - req.data.reset(new PhysicalInterfaceData(vrf_name, subtype)); + req.data.reset(new PhysicalInterfaceData(vrf_name, subtype, encap, no_arp)); table->Process(req); } @@ -442,7 +448,8 @@ PhysicalInterfaceKey::~PhysicalInterfaceKey() { } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table) const { - return new PhysicalInterface(name_, NULL, PhysicalInterface::INVALID); + return new PhysicalInterface(name_, NULL, PhysicalInterface::INVALID, + PhysicalInterface::ETHERNET, false); } Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, @@ -456,12 +463,14 @@ Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table, const PhysicalInterfaceData *phy_data = static_cast(data); - return new PhysicalInterface(name_, vrf, phy_data->subtype_); + return new PhysicalInterface(name_, vrf, phy_data->subtype_, + phy_data->encap_type_, phy_data->no_arp_); } void PhysicalInterface::PostAdd() { - InterfaceTable *table = static_cast(get_table()); + InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); + InterfaceTable *table = static_cast(get_table()); if (subtype_ != VMWARE || table->agent()->test_mode()) { return; } @@ -490,13 +499,19 @@ void PhysicalInterface::PostAdd() { close(fd); } +void PhysicalInterface::Delete() { + InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); +} + InterfaceKey *PhysicalInterfaceKey::Clone() const { return new PhysicalInterfaceKey(*this); } PhysicalInterfaceData::PhysicalInterfaceData(const std::string &vrf_name, - PhysicalInterface::SubType subtype) - : InterfaceData(), subtype_(subtype) { + PhysicalInterface::SubType subtype, + PhysicalInterface::EncapType encap, + bool no_arp) + : InterfaceData(), subtype_(subtype), encap_type_(encap), no_arp_(no_arp) { EthInit(vrf_name); } diff --git a/src/vnsw/agent/oper/nexthop.cc b/src/vnsw/agent/oper/nexthop.cc index acca500f19e..106cc0ac70f 100644 --- a/src/vnsw/agent/oper/nexthop.cc +++ b/src/vnsw/agent/oper/nexthop.cc @@ -564,6 +564,24 @@ void InterfaceNH::CreatePacketInterfaceNh(const string &ifname) { NextHopTable::GetInstance()->Process(req); } +void InterfaceNH::CreatePhysicalInterfaceNh(const string &ifname, + const MacAddress &mac) { + DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); + req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname), false, + InterfaceNHFlags::INET4)); + req.data.reset(new InterfaceNHData(Agent::GetInstance()->fabric_vrf_name(), + mac)); + NextHopTable::GetInstance()->Process(req); +} + +void InterfaceNH::DeletePhysicalInterfaceNh(const string &ifname) { + DBRequest req(DBRequest::DB_ENTRY_DELETE); + req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname), false, + InterfaceNHFlags::INET4)); + req.data.reset(NULL); + NextHopTable::GetInstance()->Process(req); +} + void InterfaceNH::DeleteHostPortReq(const string &ifname) { DBRequest req; req.oper = DBRequest::DB_ENTRY_DELETE; diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index b02593fd37f..f56289ce265 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -847,6 +847,9 @@ class InterfaceNH : public NextHop { static void DeleteNH(const uuid &intf_uuid, bool policy, uint8_t flags); static void DeleteVmInterfaceNHReq(const uuid &intf_uuid); static void CreatePacketInterfaceNh(const string &ifname); + static void CreatePhysicalInterfaceNh(const string &ifname, + const MacAddress &mac); + static void DeletePhysicalInterfaceNh(const string &ifname); static void DeleteHostPortReq(const string &ifname); static void CreateInetInterfaceNextHop(const string &ifname, const string &vrf_name); diff --git a/src/vnsw/agent/oper/physical_interface.h b/src/vnsw/agent/oper/physical_interface.h index 4cda1b90877..4df8fa1785e 100644 --- a/src/vnsw/agent/oper/physical_interface.h +++ b/src/vnsw/agent/oper/physical_interface.h @@ -17,13 +17,21 @@ class PhysicalInterface : public Interface { INVALID }; - PhysicalInterface(const std::string &name, VrfEntry *vrf, SubType subtype); + enum EncapType { + ETHERNET, // Ethernet with ARP + RAW_IP // No L2 header. Packets sent as raw-ip + }; + + PhysicalInterface(const std::string &name, VrfEntry *vrf, SubType subtype, + EncapType encap_type, bool no_arp); virtual ~PhysicalInterface(); bool CmpInterface(const DBEntry &rhs) const; std::string ToString() const { return "ETH <" + name() + ">"; } KeyPtr GetDBRequestKey() const; + virtual void Add(); + virtual void Delete(); void PostAdd(); SubType subtype() const { return subtype_; } @@ -32,24 +40,34 @@ class PhysicalInterface : public Interface { // Currently only vnware physical interface is persistent. // By default every physical interface is non-persistent. bool persistent() const {return persistent_;} + EncapType encap_type() const { return encap_type_; } + bool no_arp() const { return no_arp_; } // Helper functions static void CreateReq(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, SubType subtype); + const std::string &vrf_name, SubType subtype, + EncapType encap, bool no_arp); static void Create(InterfaceTable *table, const std::string &ifname, - const std::string &vrf_name, SubType sub_type); + const std::string &vrf_name, SubType sub_type, + EncapType encap, bool no_arp); static void DeleteReq(InterfaceTable *table, const std::string &ifname); static void Delete(InterfaceTable *table, const std::string &ifname); private: bool persistent_; SubType subtype_; + EncapType encap_type_; + bool no_arp_; DISALLOW_COPY_AND_ASSIGN(PhysicalInterface); }; struct PhysicalInterfaceData : public InterfaceData { PhysicalInterfaceData(const std::string &vrf_name, - PhysicalInterface::SubType subtype); + PhysicalInterface::SubType subtype, + PhysicalInterface::EncapType encap, + bool no_arp); PhysicalInterface::SubType subtype_; + PhysicalInterface::EncapType encap_type_; + bool no_arp_; }; struct PhysicalInterfaceKey : public InterfaceKey { diff --git a/src/vnsw/agent/oper/test/test_inet_interface.cc b/src/vnsw/agent/oper/test/test_inet_interface.cc index 1ab3311201a..931e7412820 100644 --- a/src/vnsw/agent/oper/test/test_inet_interface.cc +++ b/src/vnsw/agent/oper/test/test_inet_interface.cc @@ -284,6 +284,87 @@ TEST_F(InetInterfaceTest, ll_basic_1) { client->WaitForIdle(); } +static void DelInetConfig(Agent *agent, const Ip4Address &addr, + const Ip4Address &gw, uint8_t plen) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), addr, 32, + NULL); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + gw, 32, NULL); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + addr, plen, NULL); + WAIT_FOR(1000, 1000, + (RouteGet(agent->fabric_vrf_name(), addr, plen) == NULL)); + client->WaitForIdle(); +} + +static void AddInetRoutes(Agent *agent) { + AgentParam *agent_param = client->param(); + AgentRouteTable *table = agent->fabric_inet4_unicast_table(); + InetInterface::CreateReq(agent->interface_table(), agent_param->vhost_name(), + InetInterface::VHOST, agent->fabric_vrf_name(), + agent_param->vhost_addr(), + agent_param->vhost_plen(), + agent_param->vhost_gw(), + agent_param->eth_port(), + agent->fabric_vrf_name()); + WAIT_FOR(1000, 1000, + (RouteGet(agent->fabric_vrf_name(), agent_param->vhost_addr(), + agent_param->vhost_plen()) != NULL)); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_encap_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + + // Cleanup routes added by old inet-interface + DelInetConfig(agent_, param->vhost_addr(), param->vhost_gw(), + param->vhost_plen()); + + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, 24, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent_->fabric_vrf_name(), ip, 32)) != NULL)); + if (rt != NULL) { + nh = rt->GetActiveNextHop(); + EXPECT_TRUE(nh->GetType() == NextHop::RECEIVE); + } + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent_->fabric_vrf_name(), net, 24)) != NULL)); + if (rt != NULL) { + nh = rt->GetActiveNextHop(); + EXPECT_TRUE(nh->GetType() == NextHop::RESOLVE); + } + + DelInetConfig(agent_, Ip4Address::from_string("10.10.10.10"), + Ip4Address::from_string("10.10.10.1"), 24); + + DelInterface(this, "vhost-1", agent_->fabric_vrf_name().c_str(), + "10.10.10.1"); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + + AddInetRoutes(agent_); + client->WaitForIdle(); +} + int main(int argc, char **argv) { GETUSERARGS(); diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 91a3de51df5..4ade6b7308c 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -545,7 +545,8 @@ AddPhysicalInterface(Agent *agent, IFMapNode *node) { ::PhysicalInterface::Create(intf_table, physical_interface->display_name(), agent->fabric_vrf_name(), - true); + ::PhysicalInterface::FABRIC, ::PhysicalInterface::ETHERNET, + false); ret = true; } diff --git a/src/vnsw/agent/physical_devices/tables/physical_port.cc b/src/vnsw/agent/physical_devices/tables/physical_port.cc index 2cae4d5f266..1a50238cebc 100644 --- a/src/vnsw/agent/physical_devices/tables/physical_port.cc +++ b/src/vnsw/agent/physical_devices/tables/physical_port.cc @@ -74,7 +74,8 @@ bool PhysicalPortEntry::Copy(PhysicalPortTable *table, InterfaceTable *intf_table = table->agent()->interface_table(); PhysicalInterface::Create(intf_table, name_, table->agent()->fabric_vrf_name(), - false); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); } } diff --git a/src/vnsw/agent/pkt/test/test_flowtable.cc b/src/vnsw/agent/pkt/test/test_flowtable.cc index 58621ea78db..78e67c7e730 100644 --- a/src/vnsw/agent/pkt/test/test_flowtable.cc +++ b/src/vnsw/agent/pkt/test/test_flowtable.cc @@ -490,7 +490,8 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), FlowTableTest::eth_itf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); } diff --git a/src/vnsw/agent/pkt/test/test_pkt.cc b/src/vnsw/agent/pkt/test/test_pkt.cc index 8e105dce6e0..8c97388feae 100644 --- a/src/vnsw/agent/pkt/test/test_pkt.cc +++ b/src/vnsw/agent/pkt/test/test_pkt.cc @@ -150,7 +150,8 @@ TEST_F(PktTest, FlowAdd_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "vnet0", Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); TxMplsPacket(2, "1.1.1.2", "10.1.1.1", 0, "2.2.2.2", "3.3.3.3", 1); diff --git a/src/vnsw/agent/pkt/test/test_pkt_flow.cc b/src/vnsw/agent/pkt/test/test_pkt_flow.cc index d3d8f89f542..0a06beb245a 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_flow.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_flow.cc @@ -3637,7 +3637,8 @@ int main(int argc, char *argv[]) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_itf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_fip_cfg.cc b/src/vnsw/agent/test/test_fip_cfg.cc index ebd755ef4e4..b05ec15cafd 100644 --- a/src/vnsw/agent/test/test_fip_cfg.cc +++ b/src/vnsw/agent/test/test_fip_cfg.cc @@ -187,7 +187,8 @@ TEST_F(CfgTest, FloatingIp_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), "enet1", Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); AddArp("10.1.1.2", "00:00:00:00:00:02", "enet1"); diff --git a/src/vnsw/agent/test/test_l2route.cc b/src/vnsw/agent/test/test_l2route.cc index 7ef3487aa61..996275c6ac0 100644 --- a/src/vnsw/agent/test/test_l2route.cc +++ b/src/vnsw/agent/test/test_l2route.cc @@ -84,7 +84,8 @@ class RouteTest : public ::testing::Test { PhysicalInterface::CreateReq(agent_->interface_table(), eth_name_, agent_->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); } diff --git a/src/vnsw/agent/test/test_mirror.cc b/src/vnsw/agent/test/test_mirror.cc index cda26b5c9e0..dd67d636050 100644 --- a/src/vnsw/agent/test/test_mirror.cc +++ b/src/vnsw/agent/test/test_mirror.cc @@ -42,7 +42,8 @@ class MirrorTableTest : public ::testing::Test { nh_count_ = agent_->nexthop_table()->Size(); PhysicalInterface::CreateReq(agent_->interface_table(), eth_itf, agent_->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); fabric_gw_ip_ = Ip4Address::from_string("10.1.1.254"); uint16_t sport = 10000; unsigned long ip = 0x0a010102; diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index 524129a51bf..050301c9897 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -103,7 +103,8 @@ class RouteTest : public ::testing::Test { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_name_, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); AddResolveRoute(server1_ip_, 24); client->WaitForIdle(); diff --git a/src/vnsw/agent/test/test_vmport_cfg.cc b/src/vnsw/agent/test/test_vmport_cfg.cc index 6fd078a6a3d..02eaa2cefb0 100644 --- a/src/vnsw/agent/test/test_vmport_cfg.cc +++ b/src/vnsw/agent/test/test_vmport_cfg.cc @@ -1198,7 +1198,8 @@ TEST_F(CfgTest, Basic_1) { client->Reset(); PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), - eth_intf, vrf_name, PhysicalInterface::FABRIC); + eth_intf, vrf_name, PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); phy_intf = static_cast (agent_->interface_table()->FindActiveEntry(&key)); @@ -1206,7 +1207,8 @@ TEST_F(CfgTest, Basic_1) { PhysicalInterface::CreateReq(Agent::GetInstance()->interface_table(), eth_intf, Agent::GetInstance()->fabric_vrf_name(), - PhysicalInterface::FABRIC); + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, false); client->WaitForIdle(); phy_intf = static_cast From 07375ef224f4cb0c87b88e03c4f983c9c6bc31a8 Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sat, 8 Nov 2014 09:34:49 +0530 Subject: [PATCH 192/218] Fix UT for noarp and point-to-point flag on eth interface --- src/vnsw/agent/oper/inet_interface.cc | 10 +- src/vnsw/agent/oper/interface.cc | 5 +- src/vnsw/agent/oper/physical_interface.h | 2 +- .../agent/oper/test/test_inet_interface.cc | 148 +++++++++++++----- 4 files changed, 123 insertions(+), 42 deletions(-) diff --git a/src/vnsw/agent/oper/inet_interface.cc b/src/vnsw/agent/oper/inet_interface.cc index b85ac49d8bb..7cead1ae1e7 100644 --- a/src/vnsw/agent/oper/inet_interface.cc +++ b/src/vnsw/agent/oper/inet_interface.cc @@ -153,7 +153,8 @@ static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table, if (xconnect) { const PhysicalInterface *physical_intf = static_cast(xconnect); - if (physical_intf->no_arp()) { + if (physical_intf->no_arp() || + (physical_intf->encap_type() == PhysicalInterface::RAW_IP)) { table->AddInterfaceRouteReq(agent, agent->local_peer(), vrf->GetName(), Ip4Address(0), 0, xconnect, vn_name); @@ -186,8 +187,11 @@ static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table, const PhysicalInterface *physical_intf = static_cast(xconnect); - if (physical_intf && physical_intf->no_arp()) { - return; + if (physical_intf) { + if (physical_intf->no_arp()) + return; + if (physical_intf->encap_type() != PhysicalInterface::ETHERNET) + return; } table->AddVHostSubnetRecvRoute(agent->local_peer(), vrf->GetName(), diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 90396b96be2..583534923d4 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -499,8 +499,9 @@ void PhysicalInterface::PostAdd() { close(fd); } -void PhysicalInterface::Delete() { - InterfaceNH::CreatePhysicalInterfaceNh(name_, mac_); +bool PhysicalInterface::Delete(const DBRequest *req) { + InterfaceNH::DeletePhysicalInterfaceNh(name_); + return true; } InterfaceKey *PhysicalInterfaceKey::Clone() const { diff --git a/src/vnsw/agent/oper/physical_interface.h b/src/vnsw/agent/oper/physical_interface.h index 4df8fa1785e..63f102b2961 100644 --- a/src/vnsw/agent/oper/physical_interface.h +++ b/src/vnsw/agent/oper/physical_interface.h @@ -31,7 +31,7 @@ class PhysicalInterface : public Interface { std::string ToString() const { return "ETH <" + name() + ">"; } KeyPtr GetDBRequestKey() const; virtual void Add(); - virtual void Delete(); + virtual bool Delete(const DBRequest *req); void PostAdd(); SubType subtype() const { return subtype_; } diff --git a/src/vnsw/agent/oper/test/test_inet_interface.cc b/src/vnsw/agent/oper/test/test_inet_interface.cc index 931e7412820..cb6ad8be9b1 100644 --- a/src/vnsw/agent/oper/test/test_inet_interface.cc +++ b/src/vnsw/agent/oper/test/test_inet_interface.cc @@ -284,7 +284,7 @@ TEST_F(InetInterfaceTest, ll_basic_1) { client->WaitForIdle(); } -static void DelInetConfig(Agent *agent, const Ip4Address &addr, +static void InetTestCleanup(Agent *agent, const Ip4Address &addr, const Ip4Address &gw, uint8_t plen) { InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); @@ -299,34 +299,46 @@ static void DelInetConfig(Agent *agent, const Ip4Address &addr, client->WaitForIdle(); } -static void AddInetRoutes(Agent *agent) { - AgentParam *agent_param = client->param(); - AgentRouteTable *table = agent->fabric_inet4_unicast_table(); - InetInterface::CreateReq(agent->interface_table(), agent_param->vhost_name(), - InetInterface::VHOST, agent->fabric_vrf_name(), - agent_param->vhost_addr(), - agent_param->vhost_plen(), - agent_param->vhost_gw(), - agent_param->eth_port(), - agent->fabric_vrf_name()); - WAIT_FOR(1000, 1000, - (RouteGet(agent->fabric_vrf_name(), agent_param->vhost_addr(), - agent_param->vhost_plen()) != NULL)); +static void RestoreInetConfig(Agent *agent) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + AgentParam *param = client->param(); + table->AddGatewayRouteReq(agent->local_peer(), agent->fabric_vrf_name(), + Ip4Address(0), 0, param->vhost_gw(), + agent->fabric_vrf_name(), + MplsTable::kInvalidLabel, SecurityGroupList()); client->WaitForIdle(); } +static void DelInetConfig(Agent *agent) { + InetUnicastAgentRouteTable *table = agent->fabric_inet4_unicast_table(); + table->DeleteReq(agent->local_peer(), agent->fabric_vrf_name(), + Ip4Address(0), 0, NULL); +} + +static bool RouteValidate(Agent *agent, const Ip4Address &ip, uint8_t plen, + NextHop::Type nh_type) { + const InetUnicastRouteEntry *rt = NULL; + const NextHop *nh = NULL; + + WAIT_FOR(1000, 1000, + ((rt = RouteGet(agent->fabric_vrf_name(), ip, plen)) != NULL)); + if (rt == NULL) + return false; + + nh = rt->GetActiveNextHop(); + return (nh->GetType() == nh_type); +} + TEST_F(InetInterfaceTest, physical_eth_encap_1) { const NextHop *nh = NULL; const InetUnicastRouteEntry *rt = NULL; AgentParam *param = client->param(); - - // Cleanup routes added by old inet-interface - DelInetConfig(agent_, param->vhost_addr(), param->vhost_gw(), - param->vhost_plen()); + DelInetConfig(agent_); Ip4Address ip = Ip4Address::from_string("10.10.10.10"); Ip4Address gw = Ip4Address::from_string("10.10.10.1"); Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; PhysicalInterface::CreateReq(interface_table_, "phy-1", agent_->fabric_vrf_name(), @@ -335,33 +347,97 @@ TEST_F(InetInterfaceTest, physical_eth_encap_1) { client->WaitForIdle(); InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, - agent_->fabric_vrf_name(), ip, 24, gw, "phy-1", + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", "TEST"); client->WaitForIdle(); - WAIT_FOR(1000, 1000, - ((rt = RouteGet(agent_->fabric_vrf_name(), ip, 32)) != NULL)); - if (rt != NULL) { - nh = rt->GetActiveNextHop(); - EXPECT_TRUE(nh->GetType() == NextHop::RECEIVE); - } + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + EXPECT_TRUE(RouteValidate(agent_, net, plen, NextHop::RESOLVE)); - WAIT_FOR(1000, 1000, - ((rt = RouteGet(agent_->fabric_vrf_name(), net, 24)) != NULL)); - if (rt != NULL) { - nh = rt->GetActiveNextHop(); - EXPECT_TRUE(nh->GetType() == NextHop::RESOLVE); - } + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); + + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_raw_ip_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + DelInetConfig(agent_); + + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; + + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::RAW_IP, false); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + // Subnet route not added when l2-encap is raw-ip + EXPECT_FALSE(RouteFind(agent_->fabric_vrf_name().c_str(), net, plen)); + EXPECT_TRUE(RouteValidate(agent_, Ip4Address(0), 0, NextHop::INTERFACE)); + + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); + PhysicalInterface::DeleteReq(interface_table_, "phy-1"); + InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); + + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); + client->WaitForIdle(); +} + +TEST_F(InetInterfaceTest, physical_eth_no_arp_1) { + const NextHop *nh = NULL; + const InetUnicastRouteEntry *rt = NULL; + AgentParam *param = client->param(); + DelInetConfig(agent_); - DelInetConfig(agent_, Ip4Address::from_string("10.10.10.10"), - Ip4Address::from_string("10.10.10.1"), 24); + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + Ip4Address gw = Ip4Address::from_string("10.10.10.1"); + Ip4Address net = Ip4Address::from_string("10.10.10.0"); + uint8_t plen = 24; - DelInterface(this, "vhost-1", agent_->fabric_vrf_name().c_str(), - "10.10.10.1"); + PhysicalInterface::CreateReq(interface_table_, "phy-1", + agent_->fabric_vrf_name(), + PhysicalInterface::FABRIC, + PhysicalInterface::ETHERNET, true); + client->WaitForIdle(); + + InetInterface::CreateReq(interface_table_, "vhost-1", InetInterface::VHOST, + agent_->fabric_vrf_name(), ip, plen, gw, "phy-1", + "TEST"); + client->WaitForIdle(); + + EXPECT_TRUE(RouteValidate(agent_, ip, 32, NextHop::RECEIVE)); + // Subnet route not added when l2-encap is raw-ip + EXPECT_FALSE(RouteFind(agent_->fabric_vrf_name().c_str(), net, plen)); + EXPECT_TRUE(RouteValidate(agent_, Ip4Address(0), 0, NextHop::INTERFACE)); + + // Cleanup config by the test + InetTestCleanup(agent_, ip, gw, plen); PhysicalInterface::DeleteReq(interface_table_, "phy-1"); InetInterface::DeleteReq(interface_table_, "vhost-1"); + client->WaitForIdle(); - AddInetRoutes(agent_); + // Restore the vhost and physical-port configuration + RestoreInetConfig(agent_); client->WaitForIdle(); } From 39e2feb8db735a4067dd81fc985d202fec618764 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Tue, 11 Nov 2014 01:09:22 +0530 Subject: [PATCH 193/218] Remove tsn_ip_1 and tsn_ip_2 parsing from agent. It was meant as hack to add tunnel route for TOR VTEP address. --- src/vnsw/agent/cmn/agent.cc | 11 +---------- src/vnsw/agent/cmn/agent.h | 10 ---------- src/vnsw/agent/init/agent_param.cc | 6 +----- src/vnsw/agent/init/agent_param.h | 4 ---- 4 files changed, 2 insertions(+), 29 deletions(-) diff --git a/src/vnsw/agent/cmn/agent.cc b/src/vnsw/agent/cmn/agent.cc index 4b7fee4b999..db503af9190 100644 --- a/src/vnsw/agent/cmn/agent.cc +++ b/src/vnsw/agent/cmn/agent.cc @@ -182,14 +182,6 @@ void Agent::CopyConfig(AgentParam *params) { int count = 0; int dns_count = 0; - if (params_->tsn_ip_1().to_ulong()) { - tsn_ip_1_ = params_->tsn_ip_1().to_string(); - } - - if (params_->tsn_ip_2().to_ulong()) { - tsn_ip_2_ = params_->tsn_ip_2().to_string(); - } - if (params_->xmpp_server_1().to_ulong()) { SetAgentMcastLabelRange(count); xs_addr_[count++] = params_->xmpp_server_1().to_string(); @@ -368,8 +360,7 @@ Agent::Agent() : acl_table_(NULL), mirror_table_(NULL), vrf_assign_table_(NULL), mirror_cfg_table_(NULL), intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL), router_id_(0), prefix_len_(0), - gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), - tsn_ip_1_(), tsn_ip_2_(), xs_addr_(), xs_port_(), + gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(), xs_stime_(), xs_dns_idx_(0), dns_addr_(), dns_port_(), dss_addr_(""), dss_port_(0), dss_xs_instances_(0), discovery_client_name_(), diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h index 4a3a5def38d..0f1a1b04bc8 100644 --- a/src/vnsw/agent/cmn/agent.h +++ b/src/vnsw/agent/cmn/agent.h @@ -375,14 +375,6 @@ class Agent { AgentSignal *agent_signal() const { return agent_signal_.get(); } - const std::string &tsn_ip_1() const { - return tsn_ip_1_; - } - - const std::string &tsn_ip_2() const { - return tsn_ip_2_; - } - // TODO: Should they be moved under controller/dns/cfg? // Common XMPP Client for control-node and config clients @@ -846,8 +838,6 @@ class Agent { Ip4Address gateway_id_; std::string xs_cfg_addr_; int8_t xs_idx_; - std::string tsn_ip_1_; - std::string tsn_ip_2_; std::string xs_addr_[MAX_XMPP_SERVERS]; uint32_t xs_port_[MAX_XMPP_SERVERS]; uint64_t xs_stime_[MAX_XMPP_SERVERS]; diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index fffc7446957..b6dcdc24d8b 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -643,7 +643,6 @@ void AgentParam::InitFromConfig() { ParseCollector(); ParseVirtualHost(); - ParseServerList("TSN.server", &tsn_ip_1_, &tsn_ip_2_); ParseServerList("CONTROL-NODE.server", &xmpp_server_1_, &xmpp_server_2_); ParseServerList("DNS.server", &dns_server_1_, &dns_port_1_, &dns_server_2_, &dns_port_2_); @@ -664,8 +663,6 @@ void AgentParam::InitFromConfig() { void AgentParam::InitFromArguments() { ParseCollectorArguments(var_map_); ParseVirtualHostArguments(var_map_); - ParseServerListArguments(var_map_, tsn_ip_1_, tsn_ip_2_, - "CONTROL-NODE.server"); ParseServerListArguments(var_map_, xmpp_server_1_, xmpp_server_2_, "CONTROL-NODE.server"); ParseServerListArguments(var_map_, &dns_server_1_, &dns_port_1_, @@ -897,8 +894,7 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, enable_vhost_options_(enable_vhost_options), enable_hypervisor_options_(enable_hypervisor_options), enable_service_options_(enable_service_options), - enable_tsn_(enable_tsn), tsn_ip_1_(), tsn_ip_2_(), - vhost_(), eth_port_(), + enable_tsn_(enable_tsn), vhost_(), eth_port_(), xmpp_instance_count_(), xmpp_server_1_(), xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dns_port_1_(ContrailPorts::DnsServerPort()), diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index 3573c173451..7670713b0a8 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -77,8 +77,6 @@ class AgentParam { const std::string &agent_name() const { return agent_name_; } const std::string ð_port() const { return eth_port_; } - const Ip4Address &tsn_ip_1() const { return tsn_ip_1_; } - const Ip4Address &tsn_ip_2() const { return tsn_ip_2_; } const Ip4Address &xmpp_server_1() const { return xmpp_server_1_; } const Ip4Address &xmpp_server_2() const { return xmpp_server_2_; } const Ip4Address &dns_server_1() const { return dns_server_1_; } @@ -242,8 +240,6 @@ class AgentParam { bool enable_hypervisor_options_; bool enable_service_options_; bool enable_tsn_; - Ip4Address tsn_ip_1_; - Ip4Address tsn_ip_2_; PortInfo vhost_; std::string agent_name_; From 04a3423dd192dfa6973ac075db2679c746c6ffba Mon Sep 17 00:00:00 2001 From: Hari Date: Tue, 11 Nov 2014 03:29:45 -0800 Subject: [PATCH 194/218] add default GW route, fix vn_uve crash when VM is not present --- src/vnsw/agent/oper/vn.cc | 11 +++++++++++ src/vnsw/agent/uve/vn_uve_table_base.cc | 8 +++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index 1e9f77372c3..b9a9ac6361a 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -680,6 +680,8 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, } else { //Evaluate non key members of IPAM for changes. // no change in entry + bool gateway_changed = ((*it_old).default_gw != + (*it_new).default_gw); bool service_address_changed = ((*it_old).dns_server != (*it_new).dns_server); if ((*it_old).installed) { @@ -687,6 +689,10 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, // VNIPAM comparator does not check for gateway. // If gateway is changed then take appropriate actions. IpAddress unspecified; + if (gateway_changed) { + UpdateHostRoute((*it_old).default_gw, + (*it_new).default_gw, vn); + } if (service_address_changed) { UpdateHostRoute((*it_old).dns_server, (*it_new).dns_server, vn); @@ -696,6 +702,9 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, (*it_old).installed = (*it_new).installed; } + if (gateway_changed) { + (*it_old).default_gw = (*it_new).default_gw; + } if (service_address_changed) { (*it_old).dns_server = (*it_new).dns_server; } @@ -745,6 +754,7 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { if (vrf->GetName() == Agent::GetInstance()->linklocal_vrf_name()) { return; } + AddHostRoute(vn, ipam.default_gw); AddHostRoute(vn, ipam.dns_server); AddSubnetRoute(vn, ipam); ipam.installed = true; @@ -754,6 +764,7 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { void VnTable::DelIPAMRoutes(VnEntry *vn, VnIpam &ipam) { VrfEntry *vrf = vn->GetVrf(); if (vrf && ipam.installed) { + DelHostRoute(vn, ipam.default_gw); DelHostRoute(vn, ipam.dns_server); DelSubnetRoute(vn, ipam); ipam.installed = false; diff --git a/src/vnsw/agent/uve/vn_uve_table_base.cc b/src/vnsw/agent/uve/vn_uve_table_base.cc index 586dac34ee4..890b1e843f7 100644 --- a/src/vnsw/agent/uve/vn_uve_table_base.cc +++ b/src/vnsw/agent/uve/vn_uve_table_base.cc @@ -156,7 +156,8 @@ void VnUveTableBase::InterfaceAddHandler(const VmEntry* vm, const VnEntry* vn, UveVirtualNetworkAgent uve; - vn_uve_entry->VmAdd(vm->GetCfgName()); + if (vm) + vn_uve_entry->VmAdd(vm->GetCfgName()); vn_uve_entry->InterfaceAdd(intf); if (vn_uve_entry->BuildInterfaceVmList(uve)) { DispatchVnMsg(uve); @@ -189,15 +190,16 @@ void VnUveTableBase::InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e) } else { const VmEntry *vm = vm_port->vm(); const VnEntry *vn = vm_port->vn(); + std::string vm_name = vm? vm->GetCfgName() : agent_->NullString(); if (!state) { - state = new VnUveInterfaceState(vm->GetCfgName(), + state = new VnUveInterfaceState(vm_name, vn->GetName(), false, false); e->SetState(partition->parent(), intf_listener_id_, state); } /* Change in VM config name is not supported now */ if (state->vm_name_ != agent_->NullString() && - (state->vm_name_.compare(vm->GetCfgName()) != 0)) { + (state->vm_name_.compare(vm_name) != 0)) { assert(0); } /* Change in VN name is not supported now */ From 50d116c464792df9ee1aed38b6599073fd5f67c0 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 11 Nov 2014 09:13:43 -0800 Subject: [PATCH 195/218] check unresolved reference only if logical switch name is present. --- .../ovsdb_client/vlan_port_binding_ovsdb.cc | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index adef6a846f5..d8d5ad31eba 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -172,16 +172,20 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { return vm_intf; } - assert(!logical_switch_name_.empty()); - LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table(); - LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); - LogicalSwitchEntry *ls_entry = - static_cast(l_table->GetReference(&ls_key)); - if (!ls_entry->IsResolved()) { - OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan Binding "+ - physical_port_name_ + " vlan " + integerToString(vlan_) + - " to Logical Switch " + logical_switch_name_); - return ls_entry; + if (!logical_switch_name_.empty()) { + // Check only if logical switch name is present. + LogicalSwitchTable *l_table = + table_->client_idl()->logical_switch_table(); + LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str()); + LogicalSwitchEntry *ls_entry = + static_cast(l_table->GetReference(&ls_key)); + if (!ls_entry->IsResolved()) { + OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan " + + "Binding " + physical_port_name_ + " vlan " + + integerToString(vlan_) + " to Logical Switch " + + logical_switch_name_); + return ls_entry; + } } return NULL; From d597f18d74091111fc80de3929f3d1dbc441b48d Mon Sep 17 00:00:00 2001 From: Praveen KV Date: Wed, 12 Nov 2014 14:30:35 +0530 Subject: [PATCH 196/218] Fix merge errors --- src/vnsw/agent/init/agent_param.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index e8c7a766e64..73b69f8528b 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -923,9 +923,8 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, enable_vhost_options_(enable_vhost_options), enable_hypervisor_options_(enable_hypervisor_options), enable_service_options_(enable_service_options), - enable_tsn_(enable_tsn), vhost_(), eth_port_(), - vhost_(), agent_name_(), eth_port_(), eth_port_no_arp_(false), - eth_port_encap_type_(), + enable_tsn_(enable_tsn), vhost_(), agent_name_(), eth_port_(), + eth_port_no_arp_(false), eth_port_encap_type_(), xmpp_instance_count_(), xmpp_server_1_(), xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dns_port_1_(ContrailPorts::DnsServerPort()), From ec69c54bb7063db31366ed1d6f97eea3c59205e0 Mon Sep 17 00:00:00 2001 From: Praveen KV Date: Wed, 12 Nov 2014 15:00:00 +0530 Subject: [PATCH 197/218] Fix compilation errors in Ubuntu 14.04 --- src/base/test/task_test_util.h | 2 +- src/vnsw/agent/diag/test/test_ping.cc | 2 +- src/vnsw/agent/init/test/test_vmware.cc | 6 ++-- src/vnsw/agent/kstate/test/test_kstate.cc | 13 +++---- .../agent/oper/test/test_inet_interface.cc | 15 ++------ src/vnsw/agent/oper/test/test_intf.cc | 6 ++-- src/vnsw/agent/oper/test/test_ipv6.cc | 2 +- src/vnsw/agent/pkt/test/test_pkt_fip.cc | 35 +++++++++---------- src/vnsw/agent/services/test/metadata_test.cc | 2 -- src/vnsw/agent/test-xml/test_xml.cc | 1 - src/vnsw/agent/test-xml/test_xml_oper.cc | 1 - src/vnsw/agent/test/test_xmpp_discovery.cc | 21 +++++++---- 12 files changed, 48 insertions(+), 58 deletions(-) diff --git a/src/base/test/task_test_util.h b/src/base/test/task_test_util.h index 60440ea2504..8459cbe9601 100644 --- a/src/base/test/task_test_util.h +++ b/src/base/test/task_test_util.h @@ -90,7 +90,7 @@ do { \ #define TASK_UTIL_EXPECT_VECTOR_EQ(actual, expected) \ do { \ TASK_UTIL_EXPECT_EQ((expected).size(), (actual).size()); \ - for (int i = 0; i < (expected).size(); i++) { \ + for (int i = 0; i < (int)((expected).size()); i++) { \ TASK_UTIL_EXPECT_EQ((expected)[i], (actual)[i]); \ } \ } while (false) diff --git a/src/vnsw/agent/diag/test/test_ping.cc b/src/vnsw/agent/diag/test/test_ping.cc index 02c3807d3f2..d78c7e18a61 100644 --- a/src/vnsw/agent/diag/test/test_ping.cc +++ b/src/vnsw/agent/diag/test/test_ping.cc @@ -95,7 +95,7 @@ class DiagTest : public ::testing::Test { mac.ToArray(eth->ether_shost, sizeof(eth->ether_shost)); agent_hdr *agent = (agent_hdr *)(eth + 1); - int intf_id = ntohs(agent->hdr_ifindex); + std::size_t intf_id = ntohs(agent->hdr_ifindex); LOG(DEBUG, "Diag Callback; Agent index : " << ntohs(agent->hdr_ifindex) << " Interface index : " << GetItfId(0) << " " << GetItfId(1)); diff --git a/src/vnsw/agent/init/test/test_vmware.cc b/src/vnsw/agent/init/test/test_vmware.cc index 54deae8633e..746e2e64692 100644 --- a/src/vnsw/agent/init/test/test_vmware.cc +++ b/src/vnsw/agent/init/test/test_vmware.cc @@ -38,9 +38,9 @@ class VmwareTest : public ::testing::Test { AgentParam *param; Agent *agent; - int intf_count_; - int nh_count_; - int vrf_count_; + uint32_t intf_count_; + uint32_t nh_count_; + uint32_t vrf_count_; opt::options_description desc; opt::variables_map var_map; diff --git a/src/vnsw/agent/kstate/test/test_kstate.cc b/src/vnsw/agent/kstate/test/test_kstate.cc index dfc0b7c4d05..d55a4d997a7 100644 --- a/src/vnsw/agent/kstate/test/test_kstate.cc +++ b/src/vnsw/agent/kstate/test/test_kstate.cc @@ -91,13 +91,14 @@ class KStateTest : public ::testing::Test { void CreateVmPorts(struct PortInfo *input, int count) { CreateVmportEnv(input, count); } - void CreatePorts(int if_count, int nh_count, int rt_count, int num_ports = MAX_TEST_FD) { + void CreatePorts(uint32_t if_count, uint32_t nh_count, uint32_t rt_count, + uint32_t num_ports = MAX_TEST_FD) { int idx; client->Reset(); CreateVmPorts(input, num_ports); client->WaitForIdle(10); - for (int i = 0; i < num_ports; i++) { + for (uint32_t i = 0; i < num_ports; i++) { idx = i; WAIT_FOR(1000, 1000, (VmPortActive(input, idx) == true)); } @@ -113,10 +114,10 @@ class KStateTest : public ::testing::Test { Agent::GetInstance()->mpls_table()->Size())); if (!ksync_init_) { WAIT_FOR(1000, 1000, ((num_ports * 2) == - KSyncSockTypeMap::MplsCount())); + (uint32_t)KSyncSockTypeMap::MplsCount())); if (if_count) { WAIT_FOR(1000, 1000, ((num_ports + if_count) == - KSyncSockTypeMap::IfCount())); + (uint32_t)KSyncSockTypeMap::IfCount())); } if (nh_count) { //5 interface nexthops get created for each interface @@ -124,11 +125,11 @@ class KStateTest : public ::testing::Test { // without policy and 1 multicast - mac as all f's) //plus 4 Nexthops for each VRF (1 VRF NH and 2 Composite NHs) WAIT_FOR(1000, 1000, ((nh_count + (num_ports * 5) + 3) == - KSyncSockTypeMap::NHCount())); + (uint32_t)KSyncSockTypeMap::NHCount())); } if (rt_count) { WAIT_FOR(1000, 1000, ((rt_count + (num_ports * 2) + 1) == - KSyncSockTypeMap::RouteCount())); + (uint32_t)KSyncSockTypeMap::RouteCount())); } } } diff --git a/src/vnsw/agent/oper/test/test_inet_interface.cc b/src/vnsw/agent/oper/test/test_inet_interface.cc index cb6ad8be9b1..3aaa40716cf 100644 --- a/src/vnsw/agent/oper/test/test_inet_interface.cc +++ b/src/vnsw/agent/oper/test/test_inet_interface.cc @@ -81,9 +81,9 @@ class InetInterfaceTest : public ::testing::Test { WAIT_FOR(100, 1000, (agent_->vn_table()->Size() == 0U)); } - int intf_count_; - int nh_count_; - int vrf_count_; + uint32_t intf_count_; + uint32_t nh_count_; + uint32_t vrf_count_; Agent *agent_; InterfaceTable *interface_table_; NextHopTable *nh_table_; @@ -330,9 +330,6 @@ static bool RouteValidate(Agent *agent, const Ip4Address &ip, uint8_t plen, } TEST_F(InetInterfaceTest, physical_eth_encap_1) { - const NextHop *nh = NULL; - const InetUnicastRouteEntry *rt = NULL; - AgentParam *param = client->param(); DelInetConfig(agent_); Ip4Address ip = Ip4Address::from_string("10.10.10.10"); @@ -366,9 +363,6 @@ TEST_F(InetInterfaceTest, physical_eth_encap_1) { } TEST_F(InetInterfaceTest, physical_eth_raw_ip_1) { - const NextHop *nh = NULL; - const InetUnicastRouteEntry *rt = NULL; - AgentParam *param = client->param(); DelInetConfig(agent_); Ip4Address ip = Ip4Address::from_string("10.10.10.10"); @@ -404,9 +398,6 @@ TEST_F(InetInterfaceTest, physical_eth_raw_ip_1) { } TEST_F(InetInterfaceTest, physical_eth_no_arp_1) { - const NextHop *nh = NULL; - const InetUnicastRouteEntry *rt = NULL; - AgentParam *param = client->param(); DelInetConfig(agent_); Ip4Address ip = Ip4Address::from_string("10.10.10.10"); diff --git a/src/vnsw/agent/oper/test/test_intf.cc b/src/vnsw/agent/oper/test/test_intf.cc index da207a7a8b1..9ee0674c81b 100644 --- a/src/vnsw/agent/oper/test/test_intf.cc +++ b/src/vnsw/agent/oper/test/test_intf.cc @@ -159,7 +159,7 @@ class IntfTest : public ::testing::Test { } - int intf_count; + uint32_t intf_count; Agent *agent; }; @@ -330,7 +330,6 @@ TEST_F(IntfTest, index_reuse) { struct PortInfo input2[] = { {"vnet9", 9, "9.1.1.1", "00:00:00:00:00:01", 1, 1} }; - KSyncSockTypeMap *sock = KSyncSockTypeMap::GetKSyncSockTypeMap(); client->Reset(); CreateVmportEnv(input1, 1); @@ -372,7 +371,6 @@ TEST_F(IntfTest, entry_reuse) { struct PortInfo input1[] = { {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1} }; - KSyncSockTypeMap *sock = KSyncSockTypeMap::GetKSyncSockTypeMap(); client->Reset(); CreateVmportEnv(input1, 1); @@ -2526,7 +2524,7 @@ TEST_F(IntfTest, Intf_l2mode_deactivate_activat_via_os_state) { EXPECT_TRUE(VmPortFind(1)); VmInterface *vm_interface = static_cast(VmPortGet(1)); EXPECT_TRUE(vm_interface->vxlan_id() != 0); - uint32_t vxlan_id = vm_interface->vxlan_id(); + int vxlan_id = vm_interface->vxlan_id(); //Deactivate OS state (IF down) DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); diff --git a/src/vnsw/agent/oper/test/test_ipv6.cc b/src/vnsw/agent/oper/test/test_ipv6.cc index e987a53b3db..2b80dcc020e 100644 --- a/src/vnsw/agent/oper/test/test_ipv6.cc +++ b/src/vnsw/agent/oper/test/test_ipv6.cc @@ -63,7 +63,7 @@ class Ipv6Test : public ::testing::Test { WAIT_FOR(100, 1000, (agent_->vn_table()->Size() == 0U)); } - int intf_count_; + uint32_t intf_count_; Agent *agent_; }; diff --git a/src/vnsw/agent/pkt/test/test_pkt_fip.cc b/src/vnsw/agent/pkt/test/test_pkt_fip.cc index e0ebb3bf3b9..f23a9013db2 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_fip.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_fip.cc @@ -15,18 +15,20 @@ void RouterIdDepInit(Agent *agent) { } class FlowTest : public ::testing::Test { +public: virtual void SetUp() { + agent_ = Agent::GetInstance(); client->WaitForIdle(); - WAIT_FOR(1000, 100, - (0U == Agent::GetInstance()->pkt()->flow_table()->Size())); + WAIT_FOR(1000, 100, (0U == agent_->pkt()->flow_table()->Size())); } virtual void TearDown() { client->EnqueueFlowFlush(); client->WaitForIdle(); - WAIT_FOR(1000, 100, - (0U == Agent::GetInstance()->pkt()->flow_table()->Size())); + WAIT_FOR(1000, 100, (0U == agent_->pkt()->flow_table()->Size())); } + + Agent *agent_; }; struct PortInfo input1[] = { @@ -531,9 +533,8 @@ TEST_F(FlowTest, ServerToVm_1) { TxIpPacketUtil(vhost->id(), vhost_addr, "80.80.80.80", 1, 1); client->WaitForIdle(); EXPECT_TRUE(FlowGet(vhost->vrf()->GetName(), vhost_addr, "80.80.80.80", - 1, 0, 0, false, Agent::GetInstance()->fabric_vrf_name().c_str(), - // 1, 0, 0, false, Agent::GetInstance()->fabric_vn_name().c_str(), - Agent::GetInstance()->fabric_vn_name().c_str(), 1, + 1, 0, 0, false, agent_->fabric_vn_name().c_str(), + agent_->fabric_vn_name().c_str(), 1, true, false, vhost->flow_key_nh()->id())); EXPECT_TRUE(FlowDelete(vhost->vrf()->GetName(), vhost_addr, "80.80.80.80", @@ -552,7 +553,7 @@ TEST_F(FlowTest, ServerToVm_1) { vnet[1]->mdata_ip_addr().to_string().c_str(), 1, 0, 0, 1, "vrf1", "169.254.169.254", vnet_addr[1], 0, 0, - Agent::GetInstance()->fabric_vrf_name().c_str(), "vn1", + agent_->fabric_vn_name().c_str(), "vn1", vhost->flow_key_nh()->id(), vnet[1]->flow_key_nh()->id())); @@ -565,7 +566,7 @@ TEST_F(FlowTest, ServerToVm_1) { vnet[1]->mdata_ip_addr().to_string().c_str(), IPPROTO_UDP, 10, 20, 1, "vrf1", "169.254.169.254", vnet_addr[1], 10, 20, - Agent::GetInstance()->fabric_vrf_name().c_str(), "vn1", + agent_->fabric_vn_name().c_str(), "vn1", vhost->flow_key_nh()->id(), vnet[1]->flow_key_nh()->id())); @@ -578,10 +579,9 @@ TEST_F(FlowTest, ServerToVm_1) { vnet[1]->mdata_ip_addr().to_string().c_str(), IPPROTO_TCP, 10, 20, 1, "vrf1", "169.254.169.254", vnet_addr[1], 10, 20, - Agent::GetInstance()->fabric_vrf_name().c_str(), "vn1", + agent_->fabric_vn_name().c_str(), "vn1", vhost->flow_key_nh()->id(), vnet[1]->flow_key_nh()->id())); - // Agent::GetInstance()->fabric_vn_name().c_str(), "vn1")); RemoveMetadataService(); client->WaitForIdle(); } @@ -601,10 +601,9 @@ TEST_F(FlowTest, VmToServer_1) { vnet[1]->mdata_ip_addr().to_string().c_str(), vhost_addr, 10000, MEDATA_NAT_DPORT, "vn1", - Agent::GetInstance()->fabric_vrf_name().c_str(), + agent_->fabric_vn_name().c_str(), vnet[1]->flow_key_nh()->id(), vhost->flow_key_nh()->id())); - // Agent::GetInstance()->fabric_vn_name().c_str())); client->WaitForIdle(); TxUdpPacket(vnet[1]->id(), vnet_addr[1], "169.254.169.254", @@ -1118,7 +1117,7 @@ TEST_F(FlowTest, FlowCleanup_on_intf_del_1) { client->WaitForIdle(); EXPECT_TRUE(FlowGetNat(vhost->vrf()->GetName(), vhost_addr, vnet[7]->mdata_ip_addr().to_string().c_str(), 6, 100, 100, - Agent::GetInstance()->fabric_vrf_name(), "vn7", 2, + agent_->fabric_vn_name(), "vn7", 2, vnet[7]->vrf()->GetName().c_str(), "169.254.169.254", vnet_addr[7], 100, 100, vhost->flow_key_nh()->id(), vnet[7]->flow_key_nh()->id())); @@ -1128,7 +1127,7 @@ TEST_F(FlowTest, FlowCleanup_on_intf_del_1) { client->WaitForIdle(); EXPECT_TRUE(FlowGetNat(vnet[7]->vrf()->GetName(), vnet_addr[7], "169.254.169.254", 6, 10, 80, - "vn7", Agent::GetInstance()->fabric_vrf_name(), 3, + "vn7", agent_->fabric_vn_name(), 3, vhost->vrf()->GetName().c_str(), vnet[7]->mdata_ip_addr().to_string().c_str(), vhost_addr, 10, MEDATA_NAT_DPORT, vnet[7]->flow_key_nh()->id(), @@ -1168,8 +1167,7 @@ TEST_F(FlowTest, FlowCleanup_on_intf_del_2) { vnet[8]->mdata_ip_addr().to_string().c_str(), 100, 100, false, 2); client->WaitForIdle(); EXPECT_TRUE(FlowGetNat(vhost->vrf()->GetName(), vhost_addr, mdata_ip, - 6, 100, 100, Agent::GetInstance()->fabric_vrf_name(), "vn8", 2, - // 6, 100, 100, Agent::GetInstance()->fabric_vn_name(), "vn8", 2, + 6, 100, 100, agent_->fabric_vn_name(), "vn8", 2, "vrf8", "169.254.169.254", vnet_addr[8], 100, 100, vhost->flow_key_nh()->id(), vnet[8]->flow_key_nh()->id())); @@ -1178,8 +1176,7 @@ TEST_F(FlowTest, FlowCleanup_on_intf_del_2) { "169.254.169.254", 10, 80, false, 3); client->WaitForIdle(); EXPECT_TRUE(FlowGetNat("vrf8", vnet_addr[8], "169.254.169.254", 6, 10, 80, - "vn8", Agent::GetInstance()->fabric_vrf_name(), 3, - // "vn8", Agent::GetInstance()->fabric_vn_name(), 3, + "vn8", agent_->fabric_vn_name(), 3, vhost->vrf()->GetName().c_str(), mdata_ip, vhost_addr, 10, MEDATA_NAT_DPORT, vnet[8]->flow_key_nh()->id(), diff --git a/src/vnsw/agent/services/test/metadata_test.cc b/src/vnsw/agent/services/test/metadata_test.cc index a4deddc8d01..7a8cb57bf23 100644 --- a/src/vnsw/agent/services/test/metadata_test.cc +++ b/src/vnsw/agent/services/test/metadata_test.cc @@ -492,7 +492,6 @@ TEST_F(MetadataTest, MetadataNoLinkLocalTest) { // Send message and close server connection while message is going TEST_F(MetadataTest, MetadataCloseServerTest) { - int count = 0; MetadataProxy::MetadataStats stats; struct PortInfo input[] = { {"vnet1", 1, vm1_ip, "00:00:00:01:01:01", 1, 1}, @@ -514,7 +513,6 @@ TEST_F(MetadataTest, MetadataCloseServerTest) { for (int i = 0; i < 200; i++) { large_data.append("add more data to be sent"); } - HttpConnection *conn = SendHttpClientRequest(POST_METHOD, large_data); // stop server StopNovaApiProxy(); client->WaitForIdle(); diff --git a/src/vnsw/agent/test-xml/test_xml.cc b/src/vnsw/agent/test-xml/test_xml.cc index 61f7a7696c6..2e9e53fe010 100644 --- a/src/vnsw/agent/test-xml/test_xml.cc +++ b/src/vnsw/agent/test-xml/test_xml.cc @@ -582,7 +582,6 @@ bool AgentUtXmlPacket::ReadXml() { GetStringAttribute(node(), "tunnel_dip", &tunnel_dip_); GetUintAttribute(node(), "label", (uint16_t *)&label_); - uint16_t id = 0; if (GetUintAttribute(node(), "id", &intf_id_) == false) { cout << "Attribute \"id\" not specified for Packet. Skipping" << endl; diff --git a/src/vnsw/agent/test-xml/test_xml_oper.cc b/src/vnsw/agent/test-xml/test_xml_oper.cc index f929f7151b2..061965b040a 100644 --- a/src/vnsw/agent/test-xml/test_xml_oper.cc +++ b/src/vnsw/agent/test-xml/test_xml_oper.cc @@ -773,7 +773,6 @@ AgentUtXmlFlowValidate::~AgentUtXmlFlowValidate() { } bool AgentUtXmlFlowValidate::ReadXml() { - uint16_t id = 0; if (GetUintAttribute(node(), "nh", &nh_id_) == false) { cout << "Attribute \"nh\" not specified for Flow. Skipping" << endl; return false; diff --git a/src/vnsw/agent/test/test_xmpp_discovery.cc b/src/vnsw/agent/test/test_xmpp_discovery.cc index 6e8d1bcb446..fd300dc2e65 100644 --- a/src/vnsw/agent/test/test_xmpp_discovery.cc +++ b/src/vnsw/agent/test/test_xmpp_discovery.cc @@ -254,7 +254,8 @@ TEST_F(AgentXmppUnitTest, XmppConnection_Discovery) { client->WaitForIdle(); //wait for connection establishment - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == xs1->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == + (uint32_t)xs1->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(0)->GetXmppChannel()->GetPeerState() == xmps::READY); @@ -276,7 +277,8 @@ TEST_F(AgentXmppUnitTest, XmppConnection_Discovery) { client->WaitForIdle(); //wait for connection establishment - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == xs2->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == + (uint32_t)xs2->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(1)->GetXmppChannel()->GetPeerState() == xmps::READY); @@ -298,7 +300,8 @@ TEST_F(AgentXmppUnitTest, XmppConnection_Discovery) { client->WaitForIdle(); //wait for connection establishment - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == xs3->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == + (uint32_t)xs3->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(0)->GetXmppChannel()->GetPeerState() == xmps::READY); @@ -318,12 +321,14 @@ TEST_F(AgentXmppUnitTest, XmppConnection_Discovery) { client->WaitForIdle(); //wait for connection establishment - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == xs3->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == + (uint32_t)xs3->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(0)->GetXmppChannel()->GetPeerState() == xmps::READY); - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == xs4->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == + (uint32_t)xs4->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(1)->GetXmppChannel()->GetPeerState() == xmps::READY); @@ -349,12 +354,14 @@ TEST_F(AgentXmppUnitTest, XmppConnection_Discovery) { client->WaitForIdle(); //wait for connection establishment - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == xs5->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(0) == + (uint32_t)xs5->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(0)->GetXmppChannel()->GetPeerState() == xmps::READY); - EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == xs6->GetPort()); + EXPECT_TRUE(agent_->controller_ifmap_xmpp_port(1) == + (uint32_t)xs6->GetPort()); WAIT_FOR(1000, 10000, agent_->controller_xmpp_channel(1)->GetXmppChannel()->GetPeerState() == xmps::READY); From 199a1ed1f5a8fa50375bb7f336d1632c2e4a447b Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Wed, 12 Nov 2014 01:42:27 -0800 Subject: [PATCH 198/218] fixing compilation. --- .../ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index d8d5ad31eba..5febad3fbcf 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -180,7 +180,7 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { LogicalSwitchEntry *ls_entry = static_cast(l_table->GetReference(&ls_key)); if (!ls_entry->IsResolved()) { - OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan " + + OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan " "Binding " + physical_port_name_ + " vlan " + integerToString(vlan_) + " to Logical Switch " + logical_switch_name_); From 3e20e7529a282844593033cf9dd1b45a87b241a6 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Wed, 12 Nov 2014 17:32:19 +0530 Subject: [PATCH 199/218] Fix for multicast. Dont use peer identifier for TOR olist as its local peer. --- src/vnsw/agent/oper/multicast.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index 85e4eb2f534..e603b3dfe63 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -539,7 +539,8 @@ void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj, // - Update operation with lower sequence number sent compared to // local identifier, ignore - if (peer_identifier < obj_peer_identifier) { + if ((peer_identifier < obj_peer_identifier) && + (comp_type != Composite::TOR)) { return; } @@ -565,7 +566,11 @@ void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj, req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; req.key.reset(key); req.data.reset(tnh_data); - Agent::GetInstance()->nexthop_table()->Enqueue(&req); + if (comp_type == Composite::TOR) + Agent::GetInstance()->nexthop_table()->Process(req); + else + Agent::GetInstance()->nexthop_table()->Enqueue(&req); + MCTRACE(Log, "Enqueue add TOR TUNNEL ", Agent::GetInstance()->fabric_vrf_name(), it->daddr_.to_string(), it->label_); From 152add88ff8a99c59333086227479d888aff0aad Mon Sep 17 00:00:00 2001 From: Praveen KV Date: Wed, 12 Nov 2014 21:12:06 +0530 Subject: [PATCH 200/218] Fixes for agent to work with un-numbered vhost0 There are two issues in case when vhost0 is unnumbered in host-os. 1. When vhost0 interface is un-numbered in host-os, packets from host-os addressed to metadata-ip for VM will use an unknown-ip to vrouter. This will result in packets being dropped since source-ip is not-known. 2. When agent runs http-proxy as part of metadata services, packets from VM for metadat-service must be NAT-ed to an IP address on host-os. When vhost0 is unnumbered, VRouter must use one of the IP address in host-os. Agent is modified to support following, Agent takes the set of IP address on host-os as vhost_services_ip. Agent will use one of the vhost_services_ip for NAT-ing of packet from VM to metadata service --- src/vnsw/agent/cmn/agent.cc | 4 +- src/vnsw/agent/cmn/agent.h | 9 ++ src/vnsw/agent/contrail-vrouter-agent.conf | 4 + src/vnsw/agent/init/agent_param.cc | 38 +++++++- src/vnsw/agent/init/agent_param.h | 10 +++ src/vnsw/agent/init/contrail_init_common.cc | 30 ++++++- src/vnsw/agent/init/contrail_init_common.h | 1 + src/vnsw/agent/pkt/pkt_flow_info.cc | 17 +++- src/vnsw/agent/pkt/test/test_pkt_fip.cc | 63 ++++++++++++++ src/vnsw/agent/services/test/metadata_test.cc | 86 ++++++++++++++++++- src/vnsw/agent/test/test_agent_init.cc | 4 + src/vnsw/agent/test/test_agent_init.h | 1 + 12 files changed, 258 insertions(+), 9 deletions(-) diff --git a/src/vnsw/agent/cmn/agent.cc b/src/vnsw/agent/cmn/agent.cc index db503af9190..c1024011714 100644 --- a/src/vnsw/agent/cmn/agent.cc +++ b/src/vnsw/agent/cmn/agent.cc @@ -220,6 +220,7 @@ void Agent::CopyConfig(AgentParam *params) { router_id_configured_ = false; } + vhost_services_ip_ = router_id_; if (params_->tunnel_type() == "MPLSoUDP") TunnelType::SetDefaultType(TunnelType::MPLS_UDP); else if (params_->tunnel_type() == "VXLAN") @@ -360,7 +361,8 @@ Agent::Agent() : acl_table_(NULL), mirror_table_(NULL), vrf_assign_table_(NULL), mirror_cfg_table_(NULL), intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL), router_id_(0), prefix_len_(0), - gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(), + gateway_id_(0), vhost_services_ip_(0), xs_cfg_addr_(""), xs_idx_(0), + xs_addr_(), xs_port_(), xs_stime_(), xs_dns_idx_(0), dns_addr_(), dns_port_(), dss_addr_(""), dss_port_(0), dss_xs_instances_(0), discovery_client_name_(), diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h index 0f1a1b04bc8..523c4f373ef 100644 --- a/src/vnsw/agent/cmn/agent.h +++ b/src/vnsw/agent/cmn/agent.h @@ -373,6 +373,11 @@ class Agent { router_id_configured_ = value; } + Ip4Address vhost_services_ip() const {return vhost_services_ip_;} + void set_vhost_services_ip(const Ip4Address &addr) { + vhost_services_ip_ = addr; + } + AgentSignal *agent_signal() const { return agent_signal_.get(); } // TODO: Should they be moved under controller/dns/cfg? @@ -836,6 +841,10 @@ class Agent { Ip4Address router_id_; uint32_t prefix_len_; Ip4Address gateway_id_; + // If vhost interface in host-os is un-numbered, agent will have to run + // services such as metadata on vhost_services_ip_. + // The vhost_services_ip_ is used only in adding Flow NAT rules. + Ip4Address vhost_services_ip_; std::string xs_cfg_addr_; int8_t xs_idx_; std::string xs_addr_[MAX_XMPP_SERVERS]; diff --git a/src/vnsw/agent/contrail-vrouter-agent.conf b/src/vnsw/agent/contrail-vrouter-agent.conf index 03fec46d5e8..1b2de8d6172 100644 --- a/src/vnsw/agent/contrail-vrouter-agent.conf +++ b/src/vnsw/agent/contrail-vrouter-agent.conf @@ -125,6 +125,10 @@ log_local=1 # Physical interface name to which virtual host interface maps to # physical_interface=vnet0 +# If vhost interface is un-numbered in host-os, agent will use one of the +# vhost_service_addresses to run services (like metadata...) +vhost_service_addresses = 10.204.216.28 + # We can have multiple gateway sections with different indices in the # following format [GATEWAY-0] diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index 73b69f8528b..bcfc3dc05e4 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -272,6 +272,29 @@ void AgentParam::ParseCollector() { } } +void AgentParam::BuildAddressList(const string &val) { + vhost_service_address_list_.clear(); + if (val.empty()) { + return; + } + + vector tokens; + boost::split(tokens, val, boost::is_any_of(" ")); + vector::iterator it = tokens.begin(); + while (it != tokens.end()) { + std::string str = *it; + ++it; + + boost::algorithm::trim(str); + Ip4Address addr; + if (GetIpAddress(str, &addr)) { + vhost_service_address_list_.push_back(addr); + } else { + LOG(ERROR, "Error in parsing address " << *it); + } + } +} + void AgentParam::ParseVirtualHost() { boost::system::error_code ec; optional opt_str; @@ -280,7 +303,7 @@ void AgentParam::ParseVirtualHost() { if (opt_str = tree_.get_optional("VIRTUAL-HOST-INTERFACE.ip")) { ec = Ip4PrefixParse(opt_str.get(), &vhost_.addr_, &vhost_.plen_); - if (ec != 0 || vhost_.plen_ >= 32) { + if (ec != 0 || vhost_.plen_ > 32) { cout << "Error in config file <" << config_file_ << ">. Error parsing vhost ip-address from <" << opt_str.get() << ">\n"; @@ -295,8 +318,13 @@ void AgentParam::ParseVirtualHost() { } } - GetValueFromTree(eth_port_, + GetValueFromTree(eth_port_, "VIRTUAL-HOST-INTERFACE.physical_interface"); + + if (opt_str = tree_.get_optional + ("VIRTUAL-HOST-INTERFACE.vhost_services_ip")) { + BuildAddressList(opt_str.get()); + } } void AgentParam::ParseDiscovery() { @@ -1055,6 +1083,12 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, "Gateway IP address for virtual host") ("VIRTUAL-HOST-INTERFACE.physical_interface", opt::value(), "Physical interface name to which virtual host interface maps to") + ("VIRTUAL-HOST-INTERFACE.vhost_services_ip", + opt::value >()->multitoken(), + "Static routes to be added on vhost interface") + ("VIRTUAL-HOST-INTERFACE.physical_port_routes", + opt::value >()->multitoken(), + "Static routes to be added on physical interface") ; options_.add(vhost); } diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index 7e90fb89950..ac0e11a9359 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -19,6 +19,7 @@ class AgentParam { static const uint32_t kAgentStatsInterval = (30 * 1000); // time in millisecs static const uint32_t kFlowStatsInterval = (1000); // time in milliseconds static const uint32_t kVrouterStatsInterval = (30 * 1000); //time-millisecs + typedef std::vector AddressList; // Hypervisor mode we are working on enum Mode { @@ -34,6 +35,7 @@ class AgentParam { VCENTER }; + struct PortInfo { PortInfo() : name_(""), vrf_(""), addr_(0), prefix_(0), plen_(0), gw_(0) {} @@ -160,6 +162,11 @@ class AgentParam { } bool isTsnEnabled() const { return enable_tsn_; } + const AddressList &vhost_service_address_list() const { + return vhost_service_address_list_; + } + void BuildAddressList(const std::string &val); + protected: void set_mode(Mode m) { mode_ = m; } virtual void InitFromSystem(); @@ -300,6 +307,9 @@ class AgentParam { int si_netns_timeout_; std::string si_haproxy_ssl_cert_path_; VmwareMode vmware_mode_; + // If vhost interface is un-numbered in host-os, agent will use one of the + // vhost_service_addresses to run services (like metadata...) + AddressList vhost_service_address_list_; DISALLOW_COPY_AND_ASSIGN(AgentParam); }; diff --git a/src/vnsw/agent/init/contrail_init_common.cc b/src/vnsw/agent/init/contrail_init_common.cc index 4ceaab3f815..f4dcee13c59 100644 --- a/src/vnsw/agent/init/contrail_init_common.cc +++ b/src/vnsw/agent/init/contrail_init_common.cc @@ -124,6 +124,32 @@ static PhysicalInterface::EncapType ComputeEncapType(const string &encap) { return PhysicalInterface::ETHERNET; } +void ContrailInitCommon::CreateServiceAddress(AgentParam *param) { + InetUnicastAgentRouteTable *rt_table = + agent()->fabric_inet4_unicast_table(); + + const AgentParam::AddressList &addr_list = + param->vhost_service_address_list(); + AgentParam::AddressList::const_iterator it = addr_list.begin(); + while (it != addr_list.end()) { + rt_table->AddVHostRecvRouteReq(agent()->local_peer(), + agent()->fabric_vrf_name(), + param->vhost_name(), *it, 32, + agent()->fabric_vn_name(), false); + it++; + } + + // If vhost_service_addresses are specified, it will mean user wants + // to run services such as metadata on an IP different than vhost. + // Set vhost_services_ip_ to vhost_addr if no services_address are + // specified. Else, pick first address to run the services. + // + // The vhost_services_ip_ is used only in adding Flow NAT rules. + if (param->vhost_service_address_list().size()) { + agent()->set_vhost_services_ip(param->vhost_service_address_list()[0]); + } +} + void ContrailInitCommon::CreateInterfaces() { InterfaceTable *table = agent()->interface_table(); PhysicalInterface::EncapType type; @@ -140,7 +166,7 @@ void ContrailInitCommon::CreateInterfaces() { agent_param()->vhost_plen(), agent_param()->vhost_gw(), agent_param()->eth_port(), - agent()->fabric_vrf_name()); + agent()->fabric_vn_name()); agent()->InitXenLinkLocalIntf(); if (agent_param()->isVmwareMode()) { PhysicalInterface::Create(agent()->interface_table(), @@ -169,6 +195,8 @@ void ContrailInitCommon::CreateInterfaces() { if (agent()->vgw()) { agent()->vgw()->CreateInterfaces(); } + + CreateServiceAddress(agent_param()); } void ContrailInitCommon::InitDone() { diff --git a/src/vnsw/agent/init/contrail_init_common.h b/src/vnsw/agent/init/contrail_init_common.h index e63d597b1ce..b048965c947 100644 --- a/src/vnsw/agent/init/contrail_init_common.h +++ b/src/vnsw/agent/init/contrail_init_common.h @@ -20,6 +20,7 @@ class ContrailInitCommon : public AgentInit { void ProcessOptions(const std::string &config_file, const std::string &program_name); + void CreateServiceAddress(AgentParam *param); int Start(); // Initialization virtual methods diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 00901adea65..35fb1c25b84 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -231,7 +231,15 @@ static bool NhDecode(const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, case NextHop::ARP: { const ArpNH *arp_nh = static_cast(nh); - out->nh_ = arp_nh->GetInterface()->flow_key_nh()->id(); + if (in->intf_->type() == Interface::VM_INTERFACE) { + const VmInterface *vm_intf = + static_cast(in->intf_); + if (vm_intf->sub_type() == VmInterface::VCPE) { + out->nh_ = arp_nh->id(); + } else { + out->nh_ = arp_nh->GetInterface()->flow_key_nh()->id(); + } + } out->intf_ = arp_nh->GetInterface(); break; } @@ -528,6 +536,9 @@ void PktFlowInfo::LinkLocalServiceFromVm(const PktInfo *pkt, PktControlInfo *in, // the packet not coming to vrouter for reverse NAT. // Destination would be local host (FindLinkLocalService returns this) nat_ip_saddr = vm_port->mdata_ip_addr(); + // Services such as metadata will run on vhost_services_ip. Set nat + // address to vhost_services_ip + nat_server = Agent::GetInstance()->vhost_services_ip(); nat_sport = pkt->sport; } else { nat_ip_saddr = Agent::GetInstance()->router_id(); @@ -569,8 +580,8 @@ void PktFlowInfo::LinkLocalServiceFromHost(const PktInfo *pkt, PktControlInfo *i return; } - if ((pkt->ip_daddr.to_v4().to_ulong() != vm_port->mdata_ip_addr().to_ulong()) || - (pkt->ip_saddr.to_v4().to_ulong() != Agent::GetInstance()->router_id().to_ulong())) { + // Check if packet is destined to metadata of interface + if (pkt->ip_daddr.to_v4() != vm_port->mdata_ip_addr()) { // Force implicit deny in->rt_ = NULL; out->rt_ = NULL; diff --git a/src/vnsw/agent/pkt/test/test_pkt_fip.cc b/src/vnsw/agent/pkt/test/test_pkt_fip.cc index f23a9013db2..56802026585 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_fip.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_fip.cc @@ -586,6 +586,69 @@ TEST_F(FlowTest, ServerToVm_1) { client->WaitForIdle(); } +// Test for traffic from server to VM. Source-IP different than vhost +TEST_F(FlowTest, ServerToVm_2) { + SetupMetadataService(); + client->WaitForIdle(); + char src_ip[32] = "80.80.80.1"; + + // Packet with no route for IP-DA + TxIpPacketUtil(vhost->id(), src_ip, "80.80.80.80", 1, 1); + client->WaitForIdle(); + EXPECT_TRUE(FlowGet(vhost->vrf()->GetName(), src_ip, "80.80.80.80", + 1, 0, 0, false, agent_->fabric_vn_name().c_str(), + agent_->fabric_vn_name().c_str(), 1, + true, false, vhost->flow_key_nh()->id())); + + EXPECT_TRUE(FlowDelete(vhost->vrf()->GetName(), src_ip, "80.80.80.80", + 1, 0, 0, vhost->flow_key_nh()->id())); + + client->WaitForIdle(); + EXPECT_TRUE(FlowFail(vhost->vrf()->GetName(), src_ip, "80.80.80.80", + 1, 0, 0, vhost->flow_key_nh()->id())); + + // Ping from server to vnet1 + TxIpPacketUtil(vhost->id(), src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), 1, 1); + + EXPECT_TRUE(NatValidateFlow(1, vhost->vrf()->GetName().c_str(), + src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), + 1, 0, 0, 1, "vrf1", "169.254.169.254", + vnet_addr[1], 0, 0, + agent_->fabric_vn_name().c_str(), "vn1", + vhost->flow_key_nh()->id(), + vnet[1]->flow_key_nh()->id())); + + // UDP from server to vnet1 + TxUdpPacket(vhost->id(), src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), 10, 20); + + EXPECT_TRUE(NatValidateFlow(1, vhost->vrf()->GetName().c_str(), + src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), + IPPROTO_UDP, 10, 20, 1, "vrf1", + "169.254.169.254", vnet_addr[1], 10, 20, + agent_->fabric_vn_name().c_str(), "vn1", + vhost->flow_key_nh()->id(), + vnet[1]->flow_key_nh()->id())); + + // TCP from server to vnet1 + TxTcpPacket(vhost->id(), src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), 10, 20, false); + + EXPECT_TRUE(NatValidateFlow(1, vhost->vrf()->GetName().c_str(), + src_ip, + vnet[1]->mdata_ip_addr().to_string().c_str(), + IPPROTO_TCP, 10, 20, 1, "vrf1", "169.254.169.254", + vnet_addr[1], 10, 20, + agent_->fabric_vn_name().c_str(), "vn1", + vhost->flow_key_nh()->id(), + vnet[1]->flow_key_nh()->id())); + RemoveMetadataService(); + client->WaitForIdle(); +} + // Test for traffic from VM to server TEST_F(FlowTest, VmToServer_1) { SetupMetadataService(); diff --git a/src/vnsw/agent/services/test/metadata_test.cc b/src/vnsw/agent/services/test/metadata_test.cc index 7a8cb57bf23..941e14c6e43 100644 --- a/src/vnsw/agent/services/test/metadata_test.cc +++ b/src/vnsw/agent/services/test/metadata_test.cc @@ -24,6 +24,7 @@ #include #include #include +#include "pkt/test/test_pkt_util.h" #define MAX_WAIT_COUNT 5000 #define BUF_SIZE 8192 @@ -67,6 +68,7 @@ class MetadataTest : public ::testing::Test { }; void SetUp() { + agent_ = Agent::GetInstance(); } void TearDown() { @@ -126,8 +128,8 @@ class MetadataTest : public ::testing::Test { global_config << "\n" << "\n" << "metadata\n" - << "\n" - << "0\n" + << "169.254.169.254\n" + << "80\n" << "\n" << "" << nova_api_proxy_->GetPort() @@ -306,6 +308,7 @@ class MetadataTest : public ::testing::Test { delete request; } + Agent *agent_; private: HttpServer *nova_api_proxy_; HttpClient *vm_http_client_; @@ -331,6 +334,22 @@ TEST_F(MetadataTest, MetadataReqTest) { client->WaitForIdle(); client->Reset(); + VmInterface *intf = static_cast(VmPortGet(1)); + TxTcpPacket(intf->id(), vm1_ip, "169.254.169.254", 1000, 80, false); + client->WaitForIdle(); + FlowEntry *flow = FlowGet(0, vm1_ip, "169.254.169.254", 6, 1000, 80, + intf->flow_key_nh()->id()); + EXPECT_TRUE(flow != NULL); + FlowEntry *rflow = flow->reverse_flow_entry(); + EXPECT_TRUE(rflow != NULL); + + EXPECT_TRUE(flow->key().src_addr.to_v4() == + Ip4Address::from_string(vm1_ip)); + EXPECT_TRUE(flow->key().dst_addr.to_v4() == + Ip4Address::from_string("169.254.169.254")); + EXPECT_TRUE(rflow->key().src_addr.to_v4() == agent_->router_id()); + EXPECT_TRUE(rflow->key().dst_addr.to_v4() == intf->mdata_ip_addr()); + StartHttpClient(); // If the local address is not same as VM address in this request, @@ -375,6 +394,69 @@ TEST_F(MetadataTest, MetadataReqTest) { Agent::GetInstance()->services()->metadataproxy()->ClearStats(); } +TEST_F(MetadataTest, MetadataReqTest_services_ip) { + int count = 0; + MetadataProxy::MetadataStats stats; + struct PortInfo input[] = { + {"vnet1", 1, vm1_ip, "00:00:00:01:01:01", 1, 1}, + }; + + // Change vhost_services_ip + Ip4Address old_ip = agent_->vhost_services_ip(); + AgentParam param(agent_); + param.BuildAddressList("5.5.5.5"); + TestAgentInit *init = static_cast(client->agent_init()); + init->CreateServiceAddress(¶m); + + StartNovaApiProxy(); + SetupLinkLocalConfig(); + + CreateVmportEnv(input, 1, 0); + client->WaitForIdle(); + client->Reset(); + + StartHttpClient(); + + // If the local address is not same as VM address in this request, + // agent will have an internal error as it cannot find the VM + HttpConnection *conn = SendHttpClientRequest(GET_METHOD); + METADATA_CHECK (stats.internal_errors < 1); + EXPECT_EQ(1U, stats.requests); + EXPECT_EQ(0U, stats.responses); + EXPECT_EQ(0U, stats.proxy_sessions); + CloseClientSession(conn); + client->WaitForIdle(); + + VmInterface *intf = static_cast(VmPortGet(1)); + TxTcpPacket(intf->id(), vm1_ip, "169.254.169.254", 1000, 80, false); + client->WaitForIdle(); + FlowEntry *flow = FlowGet(0, vm1_ip, "169.254.169.254", 6, 1000, 80, + intf->flow_key_nh()->id()); + EXPECT_TRUE(flow != NULL); + FlowEntry *rflow = flow->reverse_flow_entry(); + EXPECT_TRUE(rflow != NULL); + + EXPECT_TRUE(flow->key().src_addr.to_v4() == + Ip4Address::from_string(vm1_ip)); + EXPECT_TRUE(flow->key().dst_addr.to_v4() == + Ip4Address::from_string("169.254.169.254")); + + EXPECT_TRUE(rflow->key().src_addr.to_v4() == + Ip4Address::from_string("5.5.5.5")); + EXPECT_TRUE(rflow->key().dst_addr.to_v4() == intf->mdata_ip_addr()); + client->Reset(); + StopHttpClient(); + DeleteVmportEnv(input, 1, 1, 0); + client->WaitForIdle(); + + ClearLinkLocalConfig(); + StopNovaApiProxy(); + client->WaitForIdle(); + agent_->set_vhost_services_ip(old_ip); + + Agent::GetInstance()->services()->metadataproxy()->ClearStats(); +} + // Send PUT / POST / HEAD / DELETE requests TEST_F(MetadataTest, MetadataOtherMethodsTest) { int count = 0; diff --git a/src/vnsw/agent/test/test_agent_init.cc b/src/vnsw/agent/test/test_agent_init.cc index 46309126bf0..8bf6af117bf 100644 --- a/src/vnsw/agent/test/test_agent_init.cc +++ b/src/vnsw/agent/test/test_agent_init.cc @@ -47,6 +47,10 @@ void TestAgentInit::ProcessOptions } } +void TestAgentInit::CreateServiceAddress(AgentParam *param) { + ContrailInitCommon::CreateServiceAddress(param); +} + /**************************************************************************** * Initialization routines ***************************************************************************/ diff --git a/src/vnsw/agent/test/test_agent_init.h b/src/vnsw/agent/test/test_agent_init.h index 18d2c6329c0..62f31a3ccd8 100644 --- a/src/vnsw/agent/test/test_agent_init.h +++ b/src/vnsw/agent/test/test_agent_init.h @@ -32,6 +32,7 @@ class TestAgentInit : public ContrailInitCommon { void WaitForIdle(); TestPkt0Interface *pkt0() const { return pkt0_.get(); } + void CreateServiceAddress(AgentParam *param); private: std::auto_ptr ksync_; std::auto_ptr uve_; From 41eee2b2baf0c3798b844512221b263c948d704e Mon Sep 17 00:00:00 2001 From: Praveen KV Date: Wed, 12 Nov 2014 23:23:40 +0530 Subject: [PATCH 201/218] Rename vhost_service_ip to compute_node_ip Update documentation --- src/vnsw/agent/cmn/agent.cc | 4 ++-- src/vnsw/agent/cmn/agent.h | 16 +++++++++------- src/vnsw/agent/contrail-vrouter-agent.conf | 8 +++++--- src/vnsw/agent/init/agent_param.cc | 10 +++++----- src/vnsw/agent/init/agent_param.h | 9 ++++----- src/vnsw/agent/init/contrail_init_common.cc | 18 +++++++++--------- src/vnsw/agent/init/contrail_init_common.h | 2 +- src/vnsw/agent/pkt/pkt_flow_info.cc | 6 +++--- src/vnsw/agent/services/test/metadata_test.cc | 8 ++++---- src/vnsw/agent/test/test_agent_init.cc | 4 ++-- src/vnsw/agent/test/test_agent_init.h | 2 +- 11 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/vnsw/agent/cmn/agent.cc b/src/vnsw/agent/cmn/agent.cc index c1024011714..2fa0148c34e 100644 --- a/src/vnsw/agent/cmn/agent.cc +++ b/src/vnsw/agent/cmn/agent.cc @@ -220,7 +220,7 @@ void Agent::CopyConfig(AgentParam *params) { router_id_configured_ = false; } - vhost_services_ip_ = router_id_; + compute_node_ip_ = router_id_; if (params_->tunnel_type() == "MPLSoUDP") TunnelType::SetDefaultType(TunnelType::MPLS_UDP); else if (params_->tunnel_type() == "VXLAN") @@ -361,7 +361,7 @@ Agent::Agent() : acl_table_(NULL), mirror_table_(NULL), vrf_assign_table_(NULL), mirror_cfg_table_(NULL), intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL), router_id_(0), prefix_len_(0), - gateway_id_(0), vhost_services_ip_(0), xs_cfg_addr_(""), xs_idx_(0), + gateway_id_(0), compute_node_ip_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(), xs_stime_(), xs_dns_idx_(0), dns_addr_(), dns_port_(), dss_addr_(""), dss_port_(0), dss_xs_instances_(0), diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h index 523c4f373ef..ee136a417a6 100644 --- a/src/vnsw/agent/cmn/agent.h +++ b/src/vnsw/agent/cmn/agent.h @@ -373,9 +373,9 @@ class Agent { router_id_configured_ = value; } - Ip4Address vhost_services_ip() const {return vhost_services_ip_;} - void set_vhost_services_ip(const Ip4Address &addr) { - vhost_services_ip_ = addr; + Ip4Address compute_node_ip() const {return compute_node_ip_;} + void set_compute_node_ip(const Ip4Address &addr) { + compute_node_ip_ = addr; } AgentSignal *agent_signal() const { return agent_signal_.get(); } @@ -841,10 +841,12 @@ class Agent { Ip4Address router_id_; uint32_t prefix_len_; Ip4Address gateway_id_; - // If vhost interface in host-os is un-numbered, agent will have to run - // services such as metadata on vhost_services_ip_. - // The vhost_services_ip_ is used only in adding Flow NAT rules. - Ip4Address vhost_services_ip_; + + // IP address on the compute node used by agent to run services such + // as metadata service. This is different than router_id when vhost0 + // is un-numbered interface in host-os + // The compute_node_ip_ is used only in adding Flow NAT rules. + Ip4Address compute_node_ip_; std::string xs_cfg_addr_; int8_t xs_idx_; std::string xs_addr_[MAX_XMPP_SERVERS]; diff --git a/src/vnsw/agent/contrail-vrouter-agent.conf b/src/vnsw/agent/contrail-vrouter-agent.conf index 1b2de8d6172..cd5c55dc581 100644 --- a/src/vnsw/agent/contrail-vrouter-agent.conf +++ b/src/vnsw/agent/contrail-vrouter-agent.conf @@ -125,9 +125,11 @@ log_local=1 # Physical interface name to which virtual host interface maps to # physical_interface=vnet0 -# If vhost interface is un-numbered in host-os, agent will use one of the -# vhost_service_addresses to run services (like metadata...) -vhost_service_addresses = 10.204.216.28 +# List of IP addresses assigned for the compute node other than vhost. Specify +# this only if vhost interface is un-numbered in host-os. Agent will use one +# of the compute_node_address to run services that need IP Address in host-os +# (like metadata...) +compute_node_address = 10.204.216.28 # We can have multiple gateway sections with different indices in the # following format diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc index bcfc3dc05e4..159a85b989c 100644 --- a/src/vnsw/agent/init/agent_param.cc +++ b/src/vnsw/agent/init/agent_param.cc @@ -273,7 +273,7 @@ void AgentParam::ParseCollector() { } void AgentParam::BuildAddressList(const string &val) { - vhost_service_address_list_.clear(); + compute_node_address_list_.clear(); if (val.empty()) { return; } @@ -288,7 +288,7 @@ void AgentParam::BuildAddressList(const string &val) { boost::algorithm::trim(str); Ip4Address addr; if (GetIpAddress(str, &addr)) { - vhost_service_address_list_.push_back(addr); + compute_node_address_list_.push_back(addr); } else { LOG(ERROR, "Error in parsing address " << *it); } @@ -322,7 +322,7 @@ void AgentParam::ParseVirtualHost() { "VIRTUAL-HOST-INTERFACE.physical_interface"); if (opt_str = tree_.get_optional - ("VIRTUAL-HOST-INTERFACE.vhost_services_ip")) { + ("VIRTUAL-HOST-INTERFACE.compute_node_address")) { BuildAddressList(opt_str.get()); } } @@ -1083,9 +1083,9 @@ AgentParam::AgentParam(Agent *agent, bool enable_flow_options, "Gateway IP address for virtual host") ("VIRTUAL-HOST-INTERFACE.physical_interface", opt::value(), "Physical interface name to which virtual host interface maps to") - ("VIRTUAL-HOST-INTERFACE.vhost_services_ip", + ("VIRTUAL-HOST-INTERFACE.compute_node_address", opt::value >()->multitoken(), - "Static routes to be added on vhost interface") + "List of addresses on compute node") ("VIRTUAL-HOST-INTERFACE.physical_port_routes", opt::value >()->multitoken(), "Static routes to be added on physical interface") diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h index ac0e11a9359..4cc6a8c298f 100644 --- a/src/vnsw/agent/init/agent_param.h +++ b/src/vnsw/agent/init/agent_param.h @@ -162,8 +162,8 @@ class AgentParam { } bool isTsnEnabled() const { return enable_tsn_; } - const AddressList &vhost_service_address_list() const { - return vhost_service_address_list_; + const AddressList &compute_node_address_list() const { + return compute_node_address_list_; } void BuildAddressList(const std::string &val); @@ -307,9 +307,8 @@ class AgentParam { int si_netns_timeout_; std::string si_haproxy_ssl_cert_path_; VmwareMode vmware_mode_; - // If vhost interface is un-numbered in host-os, agent will use one of the - // vhost_service_addresses to run services (like metadata...) - AddressList vhost_service_address_list_; + // List of IP addresses on the compute node. + AddressList compute_node_address_list_; DISALLOW_COPY_AND_ASSIGN(AgentParam); }; diff --git a/src/vnsw/agent/init/contrail_init_common.cc b/src/vnsw/agent/init/contrail_init_common.cc index f4dcee13c59..c4587a79925 100644 --- a/src/vnsw/agent/init/contrail_init_common.cc +++ b/src/vnsw/agent/init/contrail_init_common.cc @@ -124,12 +124,12 @@ static PhysicalInterface::EncapType ComputeEncapType(const string &encap) { return PhysicalInterface::ETHERNET; } -void ContrailInitCommon::CreateServiceAddress(AgentParam *param) { +void ContrailInitCommon::ProcessComputeAddress(AgentParam *param) { InetUnicastAgentRouteTable *rt_table = agent()->fabric_inet4_unicast_table(); const AgentParam::AddressList &addr_list = - param->vhost_service_address_list(); + param->compute_node_address_list(); AgentParam::AddressList::const_iterator it = addr_list.begin(); while (it != addr_list.end()) { rt_table->AddVHostRecvRouteReq(agent()->local_peer(), @@ -139,14 +139,14 @@ void ContrailInitCommon::CreateServiceAddress(AgentParam *param) { it++; } - // If vhost_service_addresses are specified, it will mean user wants + // If compute_node_address are specified, it will mean user wants // to run services such as metadata on an IP different than vhost. - // Set vhost_services_ip_ to vhost_addr if no services_address are - // specified. Else, pick first address to run the services. + // Set compute_node_ip_ to vhost_addr if no compute_node_address are + // specified. Else, pick first address to run in compute_node_address_list // - // The vhost_services_ip_ is used only in adding Flow NAT rules. - if (param->vhost_service_address_list().size()) { - agent()->set_vhost_services_ip(param->vhost_service_address_list()[0]); + // The compute_node_ip is used only in adding Flow NAT rules. + if (param->compute_node_address_list().size()) { + agent()->set_compute_node_ip(param->compute_node_address_list()[0]); } } @@ -196,7 +196,7 @@ void ContrailInitCommon::CreateInterfaces() { agent()->vgw()->CreateInterfaces(); } - CreateServiceAddress(agent_param()); + ProcessComputeAddress(agent_param()); } void ContrailInitCommon::InitDone() { diff --git a/src/vnsw/agent/init/contrail_init_common.h b/src/vnsw/agent/init/contrail_init_common.h index b048965c947..412e39a6668 100644 --- a/src/vnsw/agent/init/contrail_init_common.h +++ b/src/vnsw/agent/init/contrail_init_common.h @@ -20,7 +20,7 @@ class ContrailInitCommon : public AgentInit { void ProcessOptions(const std::string &config_file, const std::string &program_name); - void CreateServiceAddress(AgentParam *param); + void ProcessComputeAddress(AgentParam *param); int Start(); // Initialization virtual methods diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 35fb1c25b84..71495d8178b 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -536,9 +536,9 @@ void PktFlowInfo::LinkLocalServiceFromVm(const PktInfo *pkt, PktControlInfo *in, // the packet not coming to vrouter for reverse NAT. // Destination would be local host (FindLinkLocalService returns this) nat_ip_saddr = vm_port->mdata_ip_addr(); - // Services such as metadata will run on vhost_services_ip. Set nat - // address to vhost_services_ip - nat_server = Agent::GetInstance()->vhost_services_ip(); + // Services such as metadata will run on compute_node_ip. Set nat + // address to compute_node_ip + nat_server = Agent::GetInstance()->compute_node_ip(); nat_sport = pkt->sport; } else { nat_ip_saddr = Agent::GetInstance()->router_id(); diff --git a/src/vnsw/agent/services/test/metadata_test.cc b/src/vnsw/agent/services/test/metadata_test.cc index 941e14c6e43..42d38d39233 100644 --- a/src/vnsw/agent/services/test/metadata_test.cc +++ b/src/vnsw/agent/services/test/metadata_test.cc @@ -401,12 +401,12 @@ TEST_F(MetadataTest, MetadataReqTest_services_ip) { {"vnet1", 1, vm1_ip, "00:00:00:01:01:01", 1, 1}, }; - // Change vhost_services_ip - Ip4Address old_ip = agent_->vhost_services_ip(); + // Change compute_node_ip + Ip4Address old_ip = agent_->compute_node_ip(); AgentParam param(agent_); param.BuildAddressList("5.5.5.5"); TestAgentInit *init = static_cast(client->agent_init()); - init->CreateServiceAddress(¶m); + init->ProcessComputeAddress(¶m); StartNovaApiProxy(); SetupLinkLocalConfig(); @@ -452,7 +452,7 @@ TEST_F(MetadataTest, MetadataReqTest_services_ip) { ClearLinkLocalConfig(); StopNovaApiProxy(); client->WaitForIdle(); - agent_->set_vhost_services_ip(old_ip); + agent_->set_compute_node_ip(old_ip); Agent::GetInstance()->services()->metadataproxy()->ClearStats(); } diff --git a/src/vnsw/agent/test/test_agent_init.cc b/src/vnsw/agent/test/test_agent_init.cc index 8bf6af117bf..a739c3d2729 100644 --- a/src/vnsw/agent/test/test_agent_init.cc +++ b/src/vnsw/agent/test/test_agent_init.cc @@ -47,8 +47,8 @@ void TestAgentInit::ProcessOptions } } -void TestAgentInit::CreateServiceAddress(AgentParam *param) { - ContrailInitCommon::CreateServiceAddress(param); +void TestAgentInit::ProcessComputeAddress(AgentParam *param) { + ContrailInitCommon::ProcessComputeAddress(param); } /**************************************************************************** diff --git a/src/vnsw/agent/test/test_agent_init.h b/src/vnsw/agent/test/test_agent_init.h index 62f31a3ccd8..1f1c4c28110 100644 --- a/src/vnsw/agent/test/test_agent_init.h +++ b/src/vnsw/agent/test/test_agent_init.h @@ -32,7 +32,7 @@ class TestAgentInit : public ContrailInitCommon { void WaitForIdle(); TestPkt0Interface *pkt0() const { return pkt0_.get(); } - void CreateServiceAddress(AgentParam *param); + void ProcessComputeAddress(AgentParam *param); private: std::auto_ptr ksync_; std::auto_ptr uve_; From 6c3ef4659d18ee8e8568cb9695fdf0dc4e69267d Mon Sep 17 00:00:00 2001 From: manishsingh Date: Thu, 13 Nov 2014 10:33:10 +0530 Subject: [PATCH 202/218] If device_vn is deleted and same removed from mcast olist and olist is not yet empty then only TOR NH should be modified. Issue was that add_request was still true and it used to add back the device. Check has been modified to check for device status. --- src/vnsw/agent/oper/multicast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index e603b3dfe63..ea4875e0c46 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -196,7 +196,7 @@ void HandleTorRoute(const PhysicalDeviceVnEntry *device_vn, return; } - if (add_request) { + if (add_request && (device_vn->IsDeleted() == false)) { //TBD Make a common func to create object if (obj == NULL) { boost::system::error_code ec; From 16ca345b4eef99be5ea3a0854cb7d192a9e7adda Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Thu, 13 Nov 2014 01:16:18 -0800 Subject: [PATCH 203/218] Add Uve initialization Change Vrouter uve to use agent name instead of host name. --- .../physical_devices/ovs_tor_agent/tor_agent_init.cc | 9 +++++++++ .../physical_devices/ovs_tor_agent/tor_agent_init.h | 2 ++ src/vnsw/agent/uve/vrouter_uve_entry_base.cc | 8 ++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc index ed49f238d96..25155f0628e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,8 @@ void TorAgentInit::CreateModules() { ovsdb_client_.reset(OvsdbClient::Allocate(agent(), static_cast(agent_param()), ovs_peer_manager())); + uve_.reset(new AgentUveBase(agent(), AgentUveBase::kBandwidthInterval)); + agent()->set_uve(uve_.get()); } void TorAgentInit::CreateDBTables() { @@ -87,10 +90,12 @@ void TorAgentInit::CreateDBTables() { void TorAgentInit::RegisterDBClients() { device_manager_->RegisterDBClients(); ovsdb_client_->RegisterClients(); + uve_->RegisterDBClients(); } void TorAgentInit::InitModules() { device_manager_->Init(); + uve_->Init(); } void TorAgentInit::ConnectToController() { @@ -100,6 +105,10 @@ void TorAgentInit::ConnectToController() { /**************************************************************************** * Shutdown routines ****************************************************************************/ +void TorAgentInit::UveShutdown() { + uve_->Shutdown(); +} + void TorAgentInit::WaitForIdle() { sleep(5); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h index ed4aec4928f..6f4fe1ca914 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/tor_agent_init.h @@ -41,6 +41,7 @@ class TorAgentInit : public AgentInit { void ConnectToController(); // Shutdown virtual methods + void UveShutdown(); void WaitForIdle(); // Accessor methods @@ -52,6 +53,7 @@ class TorAgentInit : public AgentInit { std::auto_ptr device_manager_; std::auto_ptr ovs_peer_manager_; std::auto_ptr ovsdb_client_; + std::auto_ptr uve_; DISALLOW_COPY_AND_ASSIGN(TorAgentInit); }; diff --git a/src/vnsw/agent/uve/vrouter_uve_entry_base.cc b/src/vnsw/agent/uve/vrouter_uve_entry_base.cc index 22e0028b162..3426fbdf421 100644 --- a/src/vnsw/agent/uve/vrouter_uve_entry_base.cc +++ b/src/vnsw/agent/uve/vrouter_uve_entry_base.cc @@ -56,7 +56,7 @@ void VrouterUveEntryBase::DispatchVrouterMsg(const VrouterAgent &uve) { void VrouterUveEntryBase::VmWalkDone(DBTableBase *base, StringVectorPtr list) { VrouterAgent vrouter_agent; - vrouter_agent.set_name(agent_->host_name()); + vrouter_agent.set_name(agent_->agent_name()); vrouter_agent.set_virtual_machine_list(*(list.get())); DispatchVrouterMsg(vrouter_agent); } @@ -106,7 +106,7 @@ void VrouterUveEntryBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) { void VrouterUveEntryBase::VnWalkDone(DBTableBase *base, StringVectorPtr list) { VrouterAgent vrouter_agent; - vrouter_agent.set_name(agent_->host_name()); + vrouter_agent.set_name(agent_->agent_name()); vrouter_agent.set_connected_networks(*(list.get())); DispatchVrouterMsg(vrouter_agent); } @@ -156,7 +156,7 @@ void VrouterUveEntryBase::InterfaceWalkDone(DBTableBase *base, StringVectorPtr err_if_list, StringVectorPtr nova_if_list) { VrouterAgent vrouter_agent; - vrouter_agent.set_name(agent_->host_name()); + vrouter_agent.set_name(agent_->agent_name()); vrouter_agent.set_interface_list(*(if_list.get())); vrouter_agent.set_error_intf_list(*(err_if_list.get())); vrouter_agent.set_no_config_intf_list(*(nova_if_list.get())); @@ -366,7 +366,7 @@ void VrouterUveEntryBase::SendVrouterUve() { VrouterAgent vrouter_agent; bool changed = false; static bool first = true, build_info = false; - vrouter_agent.set_name(agent_->host_name()); + vrouter_agent.set_name(agent_->agent_name()); Ip4Address rid = agent_->router_id(); vector ip_list; vector dns_list; From 3f3812bd6dd81158105c1fa067251eef527a3593 Mon Sep 17 00:00:00 2001 From: Hari Date: Thu, 13 Nov 2014 12:06:54 -0800 Subject: [PATCH 204/218] take vxlan id as well in the key for the MAC to interface binding map --- src/vnsw/agent/pkt/pkt_handler.cc | 15 +++++++++------ src/vnsw/agent/pkt/pkt_handler.h | 16 ++++++++++++++-- src/vnsw/agent/services/icmp_handler.cc | 3 +-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index db883e6f8a3..2eac1e197e3 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -71,7 +71,7 @@ void PktHandler::InterfaceNotify(DBEntryBase *entry) { return; const VmInterface *vmitf = static_cast(entry); - if (vmitf->vm_mac().empty()) + if (vmitf->vm_mac().empty() || !vmitf->vn()) return; boost::system::error_code ec; @@ -79,12 +79,13 @@ void PktHandler::InterfaceNotify(DBEntryBase *entry) { if (ec) { return; } + MacVmBindingKey key(address, vmitf->vn()->GetVxLanId()); if (entry->IsDeleted()) { - mac_vm_binding_map_.erase(address); + mac_vm_binding_map_.erase(key); } else { - // assumed that VM mac doesnt change - mac_vm_binding_map_.insert(MacVmBindingPair(address, itf)); + // assumed that VM mac and VN's vxlan id do not change + mac_vm_binding_map_.insert(MacVmBindingPair(key, itf)); } } @@ -523,7 +524,8 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, if (pkt_type != PktType::UDP || pkt_info->dport != VXLAN_UDP_DEST_PORT) return false; - // Point to original L2 frame after the VXLAN header + // Get VXLAN id and point to original L2 frame after the VXLAN header + uint32_t vxlan = ntohl(*(uint32_t *)(pkt + 4)) >> 8; pkt += 8; // get to the actual packet header @@ -532,7 +534,8 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, ether_addr addr; memcpy(addr.ether_addr_octet, pkt_info->eth->ether_shost, ETH_ALEN); MacAddress address(addr); - MacVmBindingMap::iterator it = mac_vm_binding_map_.find(address); + MacVmBindingKey key(address, vxlan); + MacVmBindingMap::iterator it = mac_vm_binding_map_.find(key); if (it == mac_vm_binding_map_.end()) return false; diff --git a/src/vnsw/agent/pkt/pkt_handler.h b/src/vnsw/agent/pkt/pkt_handler.h index 8f9a685632d..cde6fb6d0e6 100644 --- a/src/vnsw/agent/pkt/pkt_handler.h +++ b/src/vnsw/agent/pkt/pkt_handler.h @@ -259,8 +259,20 @@ class PktHandler { private: friend bool ::CallPktParse(PktInfo *pkt_info, uint8_t *ptr, int len); - typedef std::map MacVmBindingMap; - typedef std::pair MacVmBindingPair; + struct MacVmBindingKey { + MacAddress mac; + int vxlan; + + MacVmBindingKey(MacAddress &m, int v) : mac(m), vxlan(v) {} + bool operator<(const MacVmBindingKey &rhs) const { + if (vxlan != rhs.vxlan) + return vxlan < rhs.vxlan; + + return mac < rhs.mac; + } + }; + typedef std::map MacVmBindingMap; + typedef std::pair MacVmBindingPair; void InterfaceNotify(DBEntryBase *entry); uint8_t *ParseEthernetHeader(PktInfo *pkt_info, diff --git a/src/vnsw/agent/services/icmp_handler.cc b/src/vnsw/agent/services/icmp_handler.cc index 27a92fb1254..233222717cd 100644 --- a/src/vnsw/agent/services/icmp_handler.cc +++ b/src/vnsw/agent/services/icmp_handler.cc @@ -66,8 +66,7 @@ void IcmpHandler::SendResponse(VmInterface *vm_intf) { char icmp_payload[icmp_len_]; memcpy(icmp_payload, icmp_, icmp_len_); - // Retain the agent-header before ethernet header - uint16_t len = EncapHeaderLen(); + uint16_t len = 0; // Form ICMP Packet with following // EthHdr - IP Header - ICMP Header From 7a083b1ebf7020b5b7202b414f74b4f40b0ea613 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Fri, 14 Nov 2014 01:29:41 -0800 Subject: [PATCH 205/218] Fix to find active entry for add/del operation. earlier if there is a temp entry created due to reference, we always fail to add the corresponding ovsdb entry. --- .../ovs_tor_agent/ovsdb_client/ovsdb_object.cc | 9 +++++++++ .../ovs_tor_agent/ovsdb_client/ovsdb_object.h | 1 + .../ovsdb_client/physical_locator_ovsdb.cc | 2 +- .../ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc | 7 ++----- .../ovsdb_client/physical_switch_ovsdb.cc | 10 +++------- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 2 +- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc index e7890baf32d..37d1295ff85 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.cc @@ -20,6 +20,15 @@ OvsdbObject::OvsdbObject(OvsdbClientIdl *idl) : KSyncObject(), OvsdbObject::~OvsdbObject() { } +KSyncEntry *OvsdbObject::FindActiveEntry(KSyncEntry *key) { + KSyncEntry *entry = Find(key); + if (entry != NULL && entry->GetState() != KSyncEntry::TEMP && + !entry->IsDeleted()) { + return entry; + } + return NULL; +} + OvsdbDBObject::OvsdbDBObject(OvsdbClientIdl *idl) : KSyncDBObject(), client_idl_(idl), walkid_(DBTableWalker::kInvalidWalkerId) { } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h index b518026510e..4d88a7eb657 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_object.h @@ -22,6 +22,7 @@ class OvsdbObject : public KSyncObject { OvsdbObject(OvsdbClientIdl *idl); virtual ~OvsdbObject(); + KSyncEntry *FindActiveEntry(KSyncEntry *key); OvsdbClientIdl *client_idl() { return client_idl_;} protected: OvsdbClientIdl *client_idl_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc index d19f2f9a804..70ae6522dfc 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_locator_ovsdb.cc @@ -45,7 +45,7 @@ void PhysicalLocatorTable::OvsdbNotify(OvsdbClientIdl::Op op, const char *dip_str = ovsdb_wrapper_physical_locator_dst_ip(row); PhysicalLocatorEntry key(this, dip_str); PhysicalLocatorEntry *entry = - static_cast(Find(&key)); + static_cast(FindActiveEntry(&key)); if (op == OvsdbClientIdl::OVSDB_DEL) { if (entry != NULL) { OVSDB_TRACE(Trace, "Delete received for Physical Locator " + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc index 6afa33479a2..cceebe030d4 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -91,18 +91,15 @@ PhysicalPortTable::~PhysicalPortTable() { void PhysicalPortTable::Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { bool override_ovs = false; - PhysicalPortEntry *entry = NULL; + PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); + PhysicalPortEntry *entry = static_cast(FindActiveEntry(&key)); if (op == OvsdbClientIdl::OVSDB_DEL) { OVSDB_TRACE(Trace, "Delete of Physical Port " + std::string(ovsdb_wrapper_physical_port_name(row))); - PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); - entry = static_cast(Find(&key)); if (entry != NULL) { Delete(entry); } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - PhysicalPortEntry key(this, ovsdb_wrapper_physical_port_name(row)); - entry = static_cast(Find(&key)); if (entry == NULL) { OVSDB_TRACE(Trace, "Add/Change of Physical Port " + std::string(ovsdb_wrapper_physical_port_name(row))); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc index 01494606da8..e310ccce627 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -62,19 +62,15 @@ PhysicalSwitchTable::~PhysicalSwitchTable() { void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row) { - const char *name = ovsdb_wrapper_physical_switch_name(row); + PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row)); + PhysicalSwitchEntry *entry = + static_cast(FindActiveEntry(&key)); if (op == OvsdbClientIdl::OVSDB_DEL) { - PhysicalSwitchEntry key(this, name); - PhysicalSwitchEntry *entry = - static_cast(Find(&key)); if (entry != NULL) { entry->SendTrace(PhysicalSwitchEntry::DEL); Delete(entry); } } else if (op == OvsdbClientIdl::OVSDB_ADD) { - PhysicalSwitchEntry key(this, name); - PhysicalSwitchEntry *entry = - static_cast(Find(&key)); if (entry == NULL) { entry = static_cast(Create(&key)); entry->SendTrace(PhysicalSwitchEntry::ADD); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index df9d9f4f772..01ec796458f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -100,7 +100,7 @@ void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op, } UnicastMacLocalEntry key(this, row); UnicastMacLocalEntry *entry = - static_cast(Find(&key)); + static_cast(FindActiveEntry(&key)); /* trigger delete if dest ip is not available */ if (op == OvsdbClientIdl::OVSDB_DEL || dest_ip == NULL) { if (entry != NULL) { From 2ba75f990c183179d986c129419bbe3794772693 Mon Sep 17 00:00:00 2001 From: Naveen N Date: Fri, 14 Nov 2014 21:09:32 -0800 Subject: [PATCH 206/218] * Upon change of physical interface or logical interface resync vm interface * Delete all ARP route dependent, when resolve route gets deleted --- src/vnsw/agent/cfg/cfg_init.cc | 13 ++++ src/vnsw/agent/cfg/cfg_init.h | 5 ++ src/vnsw/agent/controller/controller_peer.cc | 12 ++++ src/vnsw/agent/ksync/interface_ksync.cc | 19 ++++- src/vnsw/agent/ksync/nexthop_ksync.cc | 14 ++-- src/vnsw/agent/oper/agent.sandesh | 1 + src/vnsw/agent/oper/inet_unicast_route.cc | 2 +- src/vnsw/agent/oper/interface.cc | 9 +++ src/vnsw/agent/oper/nexthop.h | 5 ++ src/vnsw/agent/oper/vm_interface.cc | 76 ++++++++++++++++++-- src/vnsw/agent/oper/vm_interface.h | 8 ++- src/vnsw/agent/pkt/flow_handler.cc | 1 + src/vnsw/agent/pkt/pkt_flow_info.cc | 1 - src/vnsw/agent/services/arp_proto.cc | 1 + 14 files changed, 152 insertions(+), 15 deletions(-) diff --git a/src/vnsw/agent/cfg/cfg_init.cc b/src/vnsw/agent/cfg/cfg_init.cc index f4f8be2c796..df633cc7c7e 100644 --- a/src/vnsw/agent/cfg/cfg_init.cc +++ b/src/vnsw/agent/cfg/cfg_init.cc @@ -153,6 +153,14 @@ void AgentConfig::RegisterDBClients(DB *db) { boost::bind(&GlobalVrouter::GlobalVrouterConfig, agent_->oper_db()->global_vrouter(), _1), -1); + cfg_listener_->Register + ("physical-interface", boost::bind(&VmInterface::PhysicalPortSync, + agent_->interface_table(), _1), -1); + + cfg_listener_->Register + ("logical-interface", boost::bind(&VmInterface::LogicalPortSync, + agent_->interface_table(), _1), -1); + cfg_listener_->Register ("subnet", boost::bind(&VmInterface::SubnetSync, agent_->interface_table(), _1), -1); @@ -217,6 +225,11 @@ void AgentConfig::RegisterDBClients(DB *db) { "subnet"))); assert(cfg_route_table_); + cfg_logical_port_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "logical-interface"))); + assert(cfg_logical_port_table_); + cfg_interface_client_->Init(); } diff --git a/src/vnsw/agent/cfg/cfg_init.h b/src/vnsw/agent/cfg/cfg_init.h index 598de26c59c..b36b3aa77c5 100644 --- a/src/vnsw/agent/cfg/cfg_init.h +++ b/src/vnsw/agent/cfg/cfg_init.h @@ -61,6 +61,10 @@ class AgentConfig { return cfg_subnet_table_; } + IFMapAgentTable *cfg_logical_port_table() const { + return cfg_logical_port_table_; + } + Agent *agent() const { return agent_; } CfgFilter *cfg_filter() const { return cfg_filter_.get(); } CfgListener *cfg_listener() const { return cfg_listener_.get(); } @@ -113,6 +117,7 @@ class AgentConfig { IFMapAgentTable *cfg_route_table_; IFMapAgentTable *cfg_service_template_table_; IFMapAgentTable *cfg_subnet_table_; + IFMapAgentTable *cfg_logical_port_table_; DISALLOW_COPY_AND_ASSIGN(AgentConfig); }; diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index 44828a6a7e3..36523e45db1 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -540,6 +540,18 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, Ip4Address prefix_addr, MplsLabel *mpls = agent_->mpls_table()->FindMplsLabel(label); if (mpls != NULL) { + if (mpls->nexthop()->GetType() == NextHop::VRF) { + BgpPeer *bgp_peer = bgp_peer_id(); + ClonedLocalPath *data = + new ClonedLocalPath(unicast_sequence_number(), this, + label, item->entry.virtual_network, + item->entry.security_group_list.security_group); + rt_table->AddClonedLocalPathReq(bgp_peer, vrf_name, + prefix_addr, + prefix_len, data); + return; + } + DBEntryBase::KeyPtr key = mpls->nexthop()->GetDBRequestKey(); NextHopKey *nh_key = static_cast(key.release()); if (nh_key->GetType() != NextHop::COMPOSITE) { diff --git a/src/vnsw/agent/ksync/interface_ksync.cc b/src/vnsw/agent/ksync/interface_ksync.cc index 40d129e922b..12ccc398c6e 100644 --- a/src/vnsw/agent/ksync/interface_ksync.cc +++ b/src/vnsw/agent/ksync/interface_ksync.cc @@ -187,7 +187,11 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { if (intf->type() == Interface::VM_INTERFACE) { VmInterface *vm_port = static_cast(intf); - vm_sub_type_ = vm_port->sub_type(); + if (vm_sub_type_ != vm_port->sub_type()) { + vm_sub_type_ = vm_port->sub_type(); + ret = true; + } + if (dhcp_enable_ != vm_port->dhcp_enable_config()) { dhcp_enable_ = vm_port->dhcp_enable_config(); ret = true; @@ -212,6 +216,16 @@ bool InterfaceKSyncEntry::Sync(DBEntry *e) { ret = true; } + if (rx_vlan_id_ != vm_port->rx_vlan_id()) { + rx_vlan_id_ = vm_port->rx_vlan_id(); + ret = true; + } + + if (tx_vlan_id_ != vm_port->tx_vlan_id()) { + tx_vlan_id_ = vm_port->tx_vlan_id(); + ret = true; + } + KSyncEntryPtr parent = NULL; if (vm_port->parent()) { InterfaceKSyncEntry tmp(ksync_obj_, vm_port->parent()); @@ -425,6 +439,9 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { if (layer2_forwarding_) { flags |= VIF_FLAG_L2_ENABLED; } + if (vm_sub_type_ == VmInterface::VCPE) { + flags |= VIF_FLAG_NATIVE_VLAN_TAG; + } MacAddress mac; if (parent_.get() != NULL) { encoder.set_vifr_type(VIF_TYPE_VIRTUAL_VLAN); diff --git a/src/vnsw/agent/ksync/nexthop_ksync.cc b/src/vnsw/agent/ksync/nexthop_ksync.cc index 5aade68d748..cf66377c20f 100644 --- a/src/vnsw/agent/ksync/nexthop_ksync.cc +++ b/src/vnsw/agent/ksync/nexthop_ksync.cc @@ -195,6 +195,13 @@ bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const { return false; } + if (type_ == NextHop::ARP) { + //Policy is ignored for ARP NH + if (vrf_id_ != entry.vrf_id_) { + return vrf_id_ < entry.vrf_id_; + } + return sip_.s_addr < entry.sip_.s_addr; + } if (policy_ != entry.policy_) { return policy_ < entry.policy_; @@ -204,13 +211,6 @@ bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const { return vrf_id_ < entry.vrf_id_; } - if (type_ == NextHop::ARP) { - if (vrf_id_ != entry.vrf_id_) { - return vrf_id_ < entry.vrf_id_; - } - return sip_.s_addr < entry.sip_.s_addr; - } - if (type_ == NextHop::INTERFACE) { if (is_mcast_nh_ != entry.is_mcast_nh_) { return is_mcast_nh_ < entry.is_mcast_nh_; diff --git a/src/vnsw/agent/oper/agent.sandesh b/src/vnsw/agent/oper/agent.sandesh index 5b4b25a08e1..8127fb4d692 100644 --- a/src/vnsw/agent/oper/agent.sandesh +++ b/src/vnsw/agent/oper/agent.sandesh @@ -70,6 +70,7 @@ struct ItfSandeshData { 38: i16 rx_vlan_id; 39: string parent_interface; 40: optional string subnet; + 41: optional string sub_type; } struct VnIpamData { diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index f34839cb810..066aba301a9 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -620,7 +620,7 @@ bool InetUnicastRouteEntry::is_multicast() const { bool Inet4UnicastArpRoute::AddChangePath(Agent *agent, AgentPath *path, const AgentRoute *rt) { - bool ret = false; + bool ret = true; ArpNHKey key(vrf_name_, addr_, policy_); NextHop *nh = diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 583534923d4..2d4e5637939 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -842,6 +842,15 @@ void Interface::SetItfSandeshData(ItfSandeshData &data) const { << (int)vintf->subnet_plen(); data.set_subnet(str.str()); } + if (vintf->sub_type() == VmInterface::VCPE) { + data.set_sub_type("VCPE"); + } else if (vintf->sub_type() == VmInterface::TOR) { + data.set_sub_type("TOR"); + } else if (vintf->sub_type() == VmInterface::NOVA) { + data.set_sub_type("Tap"); + } else { + data.set_sub_type("None"); + } break; } case Interface::INET: diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index f56289ce265..65d610ade41 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -873,6 +873,11 @@ class VrfNHKey : public NextHopKey { } virtual ~VrfNHKey() { } + virtual bool NextHopKeyIsLess(const NextHopKey &rhs) const { + const VrfNHKey &key = static_cast(rhs); + return vrf_key_.IsLess(key.vrf_key_); + } + virtual NextHop *AllocEntry() const; virtual NextHopKey *Clone() const { return new VrfNHKey(vrf_key_.name_, policy_); diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index de188eda455..0f5c55a4070 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -508,7 +508,8 @@ static void ReadDhcpEnable(Agent *agent, VmInterfaceConfigData *data, //TBD Use link instead of device_owner VmInterface::SubType GetVmInterfaceSubType(Agent *agent, const std::string &device_owner) { - if (device_owner.compare("compute:nova") == 0 || agent->test_mode()) + if (device_owner.compare("compute:nova") == 0 || agent->test_mode() || + agent->tsn_enabled() == false) return VmInterface::NOVA; else return VmInterface::TOR; @@ -721,7 +722,7 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { IFMapNode *physical_node = agent_->cfg_listener()-> FindAdjacentIFMapNode(agent_, logical_node, "physical-interface"); //Add physical interface - if (AddPhysicalInterface(agent_, physical_node)) { + if (physical_node && AddPhysicalInterface(agent_, physical_node)) { autogen::PhysicalInterface *physical_interface = static_cast ( physical_node->GetObject()); @@ -729,10 +730,17 @@ bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { } } - if (!data->subnet_.is_unspecified()) { + if (!data->subnet_.is_unspecified() && + data->parent_ != agent_->NullString()) { interface_sub_type = VmInterface::VCPE; + delete key; + //Add request for a VMI of type VCPE + key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, u, + cfg->display_name()); } + data->sub_type_ = interface_sub_type; + if (cfg->mac_addresses().size()) { data->vm_mac_ = cfg->mac_addresses().at(0); } @@ -999,8 +1007,9 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old //Need not apply config for TOR VMI as it is more of an inidicative //interface. No route addition or NH addition happens for this interface. if (sub_type_ == VmInterface::TOR && - (old_subnet.is_unspecified() && old_subnet_plen == 0)) + (old_subnet.is_unspecified() && old_subnet_plen == 0)) { return; + } bool force_update = false; if (sg_changed || ecmp_mode_changed | local_pref_changed) { @@ -1316,6 +1325,11 @@ bool VmInterface::CopyConfig(const InterfaceTable *table, ret = true; } + if (sub_type_ == VCPE) { + rx_vlan_id_ = data->rx_vlan_id_; + tx_vlan_id_ = data->tx_vlan_id_; + } + if (data->parent_ != Agent::NullString()) { PhysicalInterfaceKey key(data->parent_); parent_ = static_cast @@ -1580,6 +1594,10 @@ bool VmInterface::IsIpv4Active() const { return false; } + if (subnet_.is_unspecified() == false && parent_ == NULL) { + return false; + } + if (os_oper_state_ == false) return false; @@ -3135,6 +3153,56 @@ void VmInterface::InstanceIpSync(InterfaceTable *table, IFMapNode *node) { } +void VmInterface::PhysicalPortSync(InterfaceTable *table, IFMapNode *node) { + CfgListener *cfg_listener = table->agent()->cfg_listener(); + if (cfg_listener->SkipNode(node)) { + return; + } + + DBGraph *graph = + static_cast (node->table())->GetGraph();; + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + IFMapNode *adj = static_cast(iter.operator->()); + if (table->agent()->cfg_listener()->SkipNode(adj)) { + continue; + } + + if (adj->table() == + table->agent()->cfg()->cfg_logical_port_table()) { + LogicalPortSync(table, adj); + } + } +} + + + +void VmInterface::LogicalPortSync(InterfaceTable *table, IFMapNode *node) { + CfgListener *cfg_listener = table->agent()->cfg_listener(); + if (cfg_listener->SkipNode(node)) { + return; + } + + DBGraph *graph = + static_cast (node->table())->GetGraph();; + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + IFMapNode *adj = static_cast(iter.operator->()); + if (table->agent()->cfg_listener()->SkipNode(adj)) { + continue; + } + + if (adj->table() == + table->agent()->cfg()->cfg_vm_interface_table()) { + DBRequest req; + if (table->IFNodeToReq(adj, req)) { + table->Enqueue(&req); + } + } + } +} + + void VmInterface::SubnetSync(InterfaceTable *table, IFMapNode *node) { CfgListener *cfg_listener = table->agent()->cfg_listener(); if (cfg_listener->SkipNode(node)) { diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index 529318f7c83..390d3f15d37 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -410,6 +410,8 @@ class VmInterface : public Interface { static void FloatingIpVrfSync(InterfaceTable *table, IFMapNode *node); static void VnSync(InterfaceTable *table, IFMapNode *node); static void SubnetSync(InterfaceTable *table, IFMapNode *node); + static void LogicalPortSync(InterfaceTable *table, IFMapNode *node); + static void PhysicalPortSync(InterfaceTable *table, IFMapNode *node); static void VmSync(InterfaceTable *table, IFMapNode *node); void AllocL2MplsLabel(bool force_update, bool policy_change); @@ -702,7 +704,9 @@ struct VmInterfaceConfigData : public VmInterfaceData { mirror_direction_(Interface::UNKNOWN), sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), sub_type_(VmInterface::NONE), - parent_(""), ifmap_node_(NULL), subnet_(0), subnet_plen_(0) { + parent_(""), ifmap_node_(NULL), subnet_(0), subnet_plen_(0), + rx_vlan_id_(VmInterface::kInvalidVlanId), + tx_vlan_id_(VmInterface::kInvalidVlanId) { } virtual ~VmInterfaceConfigData() { } @@ -749,6 +753,8 @@ struct VmInterfaceConfigData : public VmInterfaceData { IFMapNode *ifmap_node_; Ip4Address subnet_; uint8_t subnet_plen_; + uint16_t rx_vlan_id_; + uint16_t tx_vlan_id_; }; // Definition for structures when request queued from Nova diff --git a/src/vnsw/agent/pkt/flow_handler.cc b/src/vnsw/agent/pkt/flow_handler.cc index 7c590553c40..cb16df0de72 100644 --- a/src/vnsw/agent/pkt/flow_handler.cc +++ b/src/vnsw/agent/pkt/flow_handler.cc @@ -49,6 +49,7 @@ bool FlowHandler::Run() { pkt_info_->sport = fe->key().src_port; pkt_info_->dport = fe->key().dst_port; pkt_info_->tcp_ack = fe->is_flags_set(FlowEntry::TcpAckFlow); + pkt_info_->vrf = fe->data().vrf; } if (info.Process(pkt_info_.get(), &in, &out) == false) { diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 71495d8178b..71ee66d938b 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -931,7 +931,6 @@ void PktFlowInfo::IngressProcess(const PktInfo *pkt, PktControlInfo *in, if (out->intf_ == NULL && out->rt_) { RouteToOutInfo(out->rt_, pkt, this, in, out); } - if (out->rt_) { const NextHop* nh = out->rt_->GetActiveNextHop(); if (nh && nh->GetType() == NextHop::TUNNEL) { diff --git a/src/vnsw/agent/services/arp_proto.cc b/src/vnsw/agent/services/arp_proto.cc index 21cb59c925b..a5fdac88d90 100644 --- a/src/vnsw/agent/services/arp_proto.cc +++ b/src/vnsw/agent/services/arp_proto.cc @@ -266,6 +266,7 @@ void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) { arp_proto->del_gratuitous_arp_entry(); } entry->ClearState(part->parent(), route_table_listener_id); + state->Delete(route); delete state; } return; From 4b2fb97506ea272da204b0ef6db103fe42bc8842 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sat, 15 Nov 2014 12:42:17 -0800 Subject: [PATCH 207/218] Adding introspect to dump ovsdb Objects. --- src/ksync/ksync_object.cc | 13 +++ src/ksync/ksync_object.h | 2 + .../ovsdb_client/logical_switch_ovsdb.cc | 67 ++++++++++++++++ .../ovsdb_client/logical_switch_ovsdb.h | 4 + .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 55 +++++++++++++ .../ovs_tor_agent/ovsdb_client/ovsdb_client.h | 2 + .../ovsdb_client/ovsdb_client_session.cc | 4 + .../ovsdb_client/ovsdb_client_session.h | 1 + .../ovsdb_client/ovsdb_client_tcp.cc | 6 ++ .../ovsdb_client/ovsdb_client_tcp.h | 1 + .../ovsdb_client/physical_port_ovsdb.cc | 79 +++++++++++++++++++ .../ovsdb_client/physical_port_ovsdb.h | 4 + .../ovsdb_client/physical_switch_ovsdb.cc | 62 +++++++++++++++ .../ovsdb_client/physical_switch_ovsdb.h | 1 + 14 files changed, 301 insertions(+) diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index cf3da5dac18..d6d12dcb3c7 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -57,6 +57,19 @@ KSyncEntry *KSyncObject::Find(const KSyncEntry *key) { return NULL; } +KSyncEntry *KSyncObject::Next(const KSyncEntry *entry) { + Tree::const_iterator it; + if (entry == NULL) { + it = tree_.begin(); + } else { + it = tree_.iterator_to(*entry); + it++; + } + if (it != tree_.end()) { + return const_cast(it.operator->()); + } + return NULL; +} KSyncEntry *KSyncObject::CreateImpl(const KSyncEntry *key) { KSyncEntry *entry; if (need_index_) { diff --git a/src/ksync/ksync_object.h b/src/ksync/ksync_object.h index cadb0070c29..e0443ecde74 100644 --- a/src/ksync/ksync_object.h +++ b/src/ksync/ksync_object.h @@ -108,6 +108,8 @@ class KSyncObject { void Delete(KSyncEntry *entry); // Query function. Key is in entry KSyncEntry *Find(const KSyncEntry *key); + // Get Next Function. + KSyncEntry *Next(const KSyncEntry *entry); // Query KSyncEntry for key in entry. Create temporary entry if not present KSyncEntry *GetReference(const KSyncEntry *key); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index 5b7e633c0fd..a7d730c5aeb 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -5,6 +5,10 @@ extern "C" { #include }; +#include +#include +#include +#include #include #include #include @@ -19,6 +23,8 @@ using OVSDB::LogicalSwitchEntry; using OVSDB::LogicalSwitchTable; using OVSDB::OvsdbDBEntry; using OVSDB::OvsdbDBObject; +using OVSDB::OvsdbClient; +using OVSDB::OvsdbClientSession; LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table, const AGENT::PhysicalDeviceVnEntry *entry) : OvsdbDBEntry(table), @@ -108,6 +114,18 @@ void LogicalSwitchEntry::OvsdbChange() { table_->NotifyEvent(this, KSyncEntry::ADD_CHANGE_REQ); } +const std::string &LogicalSwitchEntry::name() const { + return name_; +} + +const std::string &LogicalSwitchEntry::device_name() const { + return device_name_; +} + +int64_t LogicalSwitchEntry::vxlan_id() const { + return vxlan_id_; +} + bool LogicalSwitchEntry::Sync(DBEntry *db_entry) { PhysicalDeviceVnEntry *entry = static_cast(db_entry); @@ -275,3 +293,52 @@ OvsdbDBEntry *LogicalSwitchTable::AllocOvsEntry(struct ovsdb_idl_row *row) { return static_cast(Create(&key)); } +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class LogicalSwitchSandeshTask : public Task { +public: + LogicalSwitchSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbLogicalSwitchResp()), resp_data_(resp_ctx) { + } + virtual ~LogicalSwitchSandeshTask() {} + virtual bool Run() { + std::vector lswitch; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + LogicalSwitchTable *table = + session->client_idl()->logical_switch_table(); + LogicalSwitchEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbLogicalSwitchEntry lentry; + lentry.set_state(entry->StateString()); + lentry.set_name(entry->name()); + lentry.set_physical_switch(entry->device_name()); + lentry.set_vxlan_id(entry->vxlan_id()); + lswitch.push_back(lentry); + entry = static_cast(table->Next(entry)); + } + resp_->set_lswitch(lswitch); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbLogicalSwitchResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(LogicalSwitchSandeshTask); +}; + +void OvsdbLogicalSwitchReq::HandleRequest() const { + LogicalSwitchSandeshTask *task = new LogicalSwitchSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h index b81a5409068..4a0b0229fa3 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.h @@ -53,6 +53,10 @@ class LogicalSwitchEntry : public OvsdbDBEntry { void OvsdbChange(); + const std::string &name() const; + const std::string &device_name() const; + int64_t vxlan_id() const; + bool Sync(DBEntry*); bool IsLess(const KSyncEntry&) const; std::string ToString() const {return "Logical Switch";} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index faa06f32103..4e8cd79b770 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -37,6 +37,21 @@ traceobject sandesh OvsdbError { Sandesh definitions for Physical Switch. ****************************************************************************/ +struct OvsdbPhysicalSwitchEntry { + 1: string state; + 2: string name; + 3: string tunnel_ip; +} + +response sandesh OvsdbPhysicalSwitchResp { + 1: list pswitch; +} + +request sandesh OvsdbPhysicalSwitchReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} + struct SandeshPhysicalSwitchInfo { 1: string op; 2: string name; @@ -46,10 +61,50 @@ traceobject sandesh OvsdbPhysicalSwitch { 1: SandeshPhysicalSwitchInfo p_switch; } +/**************************************************************************** + Sandesh definitions for Physical Port. + ****************************************************************************/ + +struct OvsdbPhysicalPortVlanInfo { + 1: i16 vlan; + 2: string logical_switch; +} + +struct OvsdbPhysicalPortEntry { + 1: string state; + 2: string name; + 3: list vlans; +} + +response sandesh OvsdbPhysicalPortResp { + 1: list port; +} + +request sandesh OvsdbPhysicalPortReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} + /**************************************************************************** Sandesh definitions for Logical Switch. ****************************************************************************/ +struct OvsdbLogicalSwitchEntry { + 1: string state; + 2: string name; + 3: string physical_switch; + 4: i64 vxlan_id; +} + +response sandesh OvsdbLogicalSwitchResp { + 1: list lswitch; +} + +request sandesh OvsdbLogicalSwitchReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} + struct SandeshLogicalSwitchInfo { 1: string op; 2: string name; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h index 6e8297c6d44..dbe931a72e0 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client.h @@ -12,6 +12,7 @@ class OvsPeerManager; class KSyncObjectManager; namespace OVSDB { +class OvsdbClientSession; class OvsdbClient { public: OvsdbClient(OvsPeerManager *manager); @@ -21,6 +22,7 @@ class OvsdbClient { virtual const std::string server() = 0; virtual uint16_t port() = 0; virtual Ip4Address tsn_ip() = 0; + virtual OvsdbClientSession *next_session(OvsdbClientSession *session) = 0; virtual void AddSessionInfo(SandeshOvsdbClient &client) = 0; KSyncObjectManager *ksync_obj_manager(); void Init(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc index 2e967598344..6a6566025b7 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.cc @@ -12,6 +12,7 @@ #include +using OVSDB::OvsdbClientIdl; using OVSDB::OvsdbClientSession; OvsdbClientSession::OvsdbClientSession(Agent *agent, OvsPeerManager *manager) : @@ -35,4 +36,7 @@ void OvsdbClientSession::OnClose() { assert(0); } +OvsdbClientIdl *OvsdbClientSession::client_idl() { + return &client_idl_; +} diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h index 4c4381d978d..0595c659315 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h @@ -27,6 +27,7 @@ class OvsdbClientSession { void MessageProcess(const u_int8_t *buf, std::size_t len); void OnEstablish(); void OnClose(); + OvsdbClientIdl *client_idl(); private: friend class OvsdbClientIdl; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc index 296598bfc54..670c0fb4630 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -10,6 +10,7 @@ #include +using OVSDB::OvsdbClientSession; using OVSDB::OvsdbClientTcp; using OVSDB::OvsdbClientTcpSession; using OVSDB::OvsdbClientTcpSessionReader; @@ -75,6 +76,11 @@ Ip4Address OvsdbClientTcp::tsn_ip() { return tsn_ip_; } +OvsdbClientSession *OvsdbClientTcp::next_session(OvsdbClientSession *session) { + return static_cast( + static_cast(session_)); +} + void OvsdbClientTcp::AddSessionInfo(SandeshOvsdbClient &client){ SandeshOvsdbClientSession session; std::vector session_list; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h index 590c0169238..889d5ace444 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.h @@ -84,6 +84,7 @@ class OvsdbClientTcp : public TcpServer, public OvsdbClient { const std::string server(); uint16_t port(); Ip4Address tsn_ip(); + OvsdbClientSession *next_session(OvsdbClientSession *session); void AddSessionInfo(SandeshOvsdbClient &client); private: friend class OvsdbClientTcpSession; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc index cceebe030d4..8857cf7d5a8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -5,10 +5,20 @@ extern "C" { #include }; + +#include + +#include +#include +#include +#include + #include #include #include +using OVSDB::OvsdbClient; +using OVSDB::OvsdbClientSession; using OVSDB::PhysicalPortEntry; using OVSDB::PhysicalPortTable; @@ -67,6 +77,15 @@ void PhysicalPortEntry::DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls) { binding_table_.erase(vlan); } +const std::string &PhysicalPortEntry::name() const { + return name_; +} + +const PhysicalPortEntry::VlanLSTable & +PhysicalPortEntry::ovs_binding_table() const { + return ovs_binding_table_; +} + void PhysicalPortEntry::OverrideOvs() { struct ovsdb_idl_txn *txn = table_->client_idl()->CreateTxn(this); Encode(txn); @@ -154,3 +173,63 @@ KSyncEntry *PhysicalPortTable::Alloc(const KSyncEntry *key, uint32_t index) { return entry; } +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class PhysicalPortSandeshTask : public Task { +public: + PhysicalPortSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbPhysicalPortResp()), resp_data_(resp_ctx) { + } + virtual ~PhysicalPortSandeshTask() {} + virtual bool Run() { + std::vector port_list; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + PhysicalPortTable *table = + session->client_idl()->physical_port_table(); + PhysicalPortEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbPhysicalPortEntry pentry; + pentry.set_state(entry->StateString()); + pentry.set_name(entry->name()); + const PhysicalPortEntry::VlanLSTable &bindings = + entry->ovs_binding_table(); + PhysicalPortEntry::VlanLSTable::const_iterator it = + bindings.begin(); + std::vector vlan_list; + for (; it != bindings.end(); it++) { + OvsdbPhysicalPortVlanInfo vlan; + vlan.set_vlan(it->first); + vlan.set_logical_switch(it->second->name()); + vlan_list.push_back(vlan); + } + pentry.set_vlans(vlan_list); + port_list.push_back(pentry); + entry = static_cast(table->Next(entry)); + } + resp_->set_port(port_list); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbPhysicalPortResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(PhysicalPortSandeshTask); +}; + +void OvsdbPhysicalPortReq::HandleRequest() const { + PhysicalPortSandeshTask *task = new PhysicalPortSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h index 9c6837e3c89..c7a4c21abc0 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h @@ -33,6 +33,10 @@ class PhysicalPortEntry : public OvsdbEntry { void Encode(struct ovsdb_idl_txn *); void AddBinding(int16_t vlan, LogicalSwitchEntry *ls); void DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls); + + const std::string &name() const; + const VlanLSTable &ovs_binding_table() const; + private: friend class PhysicalPortTable; void OverrideOvs(); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc index e310ccce627..788e261d372 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc @@ -5,10 +5,18 @@ extern "C" { #include }; + +#include + +#include +#include #include +#include #include #include +using OVSDB::OvsdbClient; +using OVSDB::OvsdbClientSession; using OVSDB::PhysicalSwitchEntry; using OVSDB::PhysicalSwitchTable; @@ -24,6 +32,10 @@ Ip4Address &PhysicalSwitchEntry::tunnel_ip() { return tunnel_ip_; } +const std::string &PhysicalSwitchEntry::name() { + return name_; +} + void PhysicalSwitchEntry::set_tunnel_ip(std::string ip) { boost::system::error_code ec; tunnel_ip_ = Ip4Address::from_string(ip, ec); @@ -88,3 +100,53 @@ KSyncEntry *PhysicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) { return entry; } + +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class PhysicalSwitchSandeshTask : public Task { +public: + PhysicalSwitchSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbPhysicalSwitchResp()), resp_data_(resp_ctx) { + } + virtual ~PhysicalSwitchSandeshTask() {} + virtual bool Run() { + std::vector pswitch; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + PhysicalSwitchTable *table = + session->client_idl()->physical_switch_table(); + PhysicalSwitchEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbPhysicalSwitchEntry pentry; + pentry.set_state(entry->StateString()); + pentry.set_name(entry->name()); + pentry.set_tunnel_ip(entry->tunnel_ip().to_string()); + pswitch.push_back(pentry); + entry = static_cast(table->Next(entry)); + } + resp_->set_pswitch(pswitch); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbPhysicalSwitchResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchSandeshTask); +}; + +void OvsdbPhysicalSwitchReq::HandleRequest() const { + PhysicalSwitchSandeshTask *task = new PhysicalSwitchSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h index cfe42b8529c..cc37728d21c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.h @@ -30,6 +30,7 @@ class PhysicalSwitchEntry : public OvsdbEntry { ~PhysicalSwitchEntry(); Ip4Address &tunnel_ip(); + const std::string &name(); void set_tunnel_ip(std::string ip); bool IsLess(const KSyncEntry&) const; std::string ToString() const {return "Physical Switch";} From f684f01ff0b1cac7fab0709c13b5c1ac3544cbd4 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sat, 15 Nov 2014 13:42:37 -0800 Subject: [PATCH 208/218] fix updation of logical switch name, when vm intf is resolved. --- .../ovsdb_client/vlan_port_binding_ovsdb.cc | 17 +++++++++++++---- .../ovsdb_client/vm_interface_ksync.cc | 4 ++++ .../ovsdb_client/vm_interface_ksync.h | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index 5febad3fbcf..3f7056c7272 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -170,6 +170,9 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { physical_port_name_ + " vlan " + integerToString(vlan_) + " to Logical Switch " + logical_switch_name_); return vm_intf; + } else if (logical_switch_name_.empty()) { + // update latest name after resolution. + logical_switch_name_ = vm_intf->vn_name(); } if (!logical_switch_name_.empty()) { @@ -224,10 +227,16 @@ KSyncDBObject::DBFilterResp VlanPortBindingTable::DBEntryFilter( const DBEntry *entry) { const AGENT::VlanLogicalPortEntry *l_port = static_cast(entry); - if (l_port->physical_port() == NULL || - l_port->physical_port()->device() == NULL) { - // Since we need physical port name and device name as key, ignore entry - // if physical port or device is not yet present. + // Since we need physical port name and device name as key, ignore entry + // if physical port or device is not yet present. + if (l_port->physical_port() == NULL) { + OVSDB_TRACE(Trace, "Ignoring Port Vlan Binding due to physical port " + "unavailablity Logical port = " + l_port->name()); + return DBFilterIgnore; // TODO(Prabhjot) check if Delete is required. + } + if (l_port->physical_port()->device() == NULL) { + OVSDB_TRACE(Trace, "Ignoring Port Vlan Binding due to device " + "unavailablity Logical port = " + l_port->name()); return DBFilterIgnore; // TODO(Prabhjot) check if Delete is required. } return DBFilterAccept; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc index 0213c31e3fc..839989d6a65 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.cc @@ -66,6 +66,10 @@ KSyncEntry *VMInterfaceKSyncEntry::UnresolvedReference() { return NULL; } +const std::string &VMInterfaceKSyncEntry::vn_name() const { + return vn_name_; +} + VMInterfaceKSyncObject::VMInterfaceKSyncObject(OvsdbClientIdl *idl, DBTable *table) : OvsdbDBObject(idl, table) { } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h index 267720ef299..005a459b38c 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vm_interface_ksync.h @@ -44,6 +44,8 @@ class VMInterfaceKSyncEntry : public OvsdbDBEntry { std::string ToString() const {return "VM Interface Ksync";} KSyncEntry* UnresolvedReference(); + const std::string &vn_name() const; + private: friend class VMInterfaceKSyncObject; boost::uuids::uuid uuid_; From a9e411da403f9665924754eae110f7f05183a763 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Sun, 16 Nov 2014 21:31:04 -0800 Subject: [PATCH 209/218] Add error string to the transaction failed message. --- .../ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc | 5 +++-- .../ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c | 6 ++++++ .../ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 60f795b2e2f..ba1948cf2ee 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -60,13 +60,14 @@ void ovsdb_wrapper_idl_txn_ack(void *idl_base, struct ovsdb_idl_txn *txn) { OvsdbClientIdl *client_idl = (OvsdbClientIdl *) idl_base; OvsdbEntryBase *entry = client_idl->pending_txn_[txn]; bool success = ovsdb_wrapper_is_txn_success(txn); - client_idl->DeleteTxn(txn); if (!success) { - OVSDB_TRACE(Error, "Transaction failed"); + OVSDB_TRACE(Error, "Transaction failed: " + + std::string(ovsdb_wrapper_txn_get_error(txn))); // we don't handle the case where txn fails, when entry is not present // case of unicast_mac_remote entry. assert(entry != NULL); } + client_idl->DeleteTxn(txn); if (entry) entry->Ack(success); } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index 48f8ca245f5..c366098fb5a 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -168,6 +168,12 @@ ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn) return ovsdb_idl_is_txn_success(txn); } +const char * +ovsdb_wrapper_txn_get_error(struct ovsdb_idl_txn *txn) +{ + return ovsdb_idl_txn_get_error(txn); +} + struct jsonrpc_msg * ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn) { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index aca6ed785b1..3f0e0f87468 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -39,6 +39,7 @@ void ovsdb_wrapper_jsonrpc_msg_destroy(struct jsonrpc_msg *msg); struct ovsdb_idl_txn *ovsdb_wrapper_idl_txn_create(struct ovsdb_idl *idl); void ovsdb_wrapper_idl_txn_destroy(struct ovsdb_idl_txn *txn); bool ovsdb_wrapper_is_txn_success(struct ovsdb_idl_txn *txn); +const char *ovsdb_wrapper_txn_get_error(struct ovsdb_idl_txn *txn); struct jsonrpc_msg *ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn); /* Physical Switch */ From 90871b3bec5f08a9b189d024829100990e105a30 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Mon, 17 Nov 2014 00:39:06 -0800 Subject: [PATCH 210/218] Add stats in physical ports. Display stats in introspect. --- .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 4 ++ .../ovsdb_client/ovsdb_wrapper.c | 39 +++++++++++++++++++ .../ovsdb_client/ovsdb_wrapper.h | 13 +++++++ .../ovsdb_client/physical_port_ovsdb.cc | 30 ++++++++++++++ .../ovsdb_client/physical_port_ovsdb.h | 3 ++ 5 files changed, 89 insertions(+) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index 4e8cd79b770..f3a9e2e1615 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -68,6 +68,10 @@ traceobject sandesh OvsdbPhysicalSwitch { struct OvsdbPhysicalPortVlanInfo { 1: i16 vlan; 2: string logical_switch; + 3: i64 in_pkts; + 4: i64 in_bytes; + 5: i64 out_pkts; + 6: i64 out_bytes; } struct OvsdbPhysicalPortEntry { diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c index c366098fb5a..ef2ef2fa89f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.c @@ -274,6 +274,29 @@ ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, } } +size_t +ovsdb_wrapper_physical_port_vlan_stats_count(struct ovsdb_idl_row *row) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + return p->n_vlan_stats; +} + +void +ovsdb_wrapper_physical_port_vlan_stats(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_stats *stats) +{ + struct vteprec_physical_port *p = + row ? CONTAINER_OF(row, struct vteprec_physical_port, header_) : NULL; + size_t count = p->n_vlan_stats; + size_t i = 0; + while (i < count) { + stats[i].vlan = p->key_vlan_stats[i]; + stats[i].stats = ((struct ovsdb_idl_row *) ((char *)(p->value_vlan_stats[i]) + offsetof(struct vteprec_logical_binding_stats, header_))); + i++; + } +} + void ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *txn, struct ovsdb_idl_row *row, @@ -529,3 +552,19 @@ ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row) return &(mcast->locator_set->header_); } +/* logical binding stats */ +void +ovsdb_wrapper_get_logical_binding_stats(struct ovsdb_idl_row *row, + int64_t *in_pkts, int64_t *in_bytes, + int64_t *out_pkts, int64_t *out_bytes) +{ + struct vteprec_logical_binding_stats *stats = + row ? CONTAINER_OF(row, struct vteprec_logical_binding_stats, header_) : NULL; + if (row == NULL) + return; + *in_pkts = stats->packets_from_local; + *in_bytes = stats->bytes_from_local; + *out_pkts = stats->packets_to_local; + *out_bytes = stats->bytes_to_local; +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h index 3f0e0f87468..cb88936a5ee 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_wrapper.h @@ -12,6 +12,11 @@ struct ovsdb_wrapper_port_vlan_binding { struct ovsdb_idl_row *ls; }; +struct ovsdb_wrapper_port_vlan_stats { + int64_t vlan; + struct ovsdb_idl_row *stats; +}; + /* Wrapper for C APIs */ struct ovsdb_idl * ovsdb_wrapper_idl_create(); void ovsdb_wrapper_idl_destroy(struct ovsdb_idl *idl); @@ -58,6 +63,9 @@ char *ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row); size_t ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row); void ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, struct ovsdb_wrapper_port_vlan_binding*); +size_t ovsdb_wrapper_physical_port_vlan_stats_count(struct ovsdb_idl_row *row); +void ovsdb_wrapper_physical_port_vlan_stats(struct ovsdb_idl_row *row, + struct ovsdb_wrapper_port_vlan_stats*); void ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *, struct ovsdb_idl_row *, struct ovsdb_wrapper_port_vlan_binding*, size_t binding_count); @@ -102,5 +110,10 @@ ovsdb_wrapper_mcast_mac_remote_logical_switch(struct ovsdb_idl_row *row); struct ovsdb_idl_row * ovsdb_wrapper_mcast_mac_remote_physical_locator_set(struct ovsdb_idl_row *row); +/* logical binding stats */ +void ovsdb_wrapper_get_logical_binding_stats(struct ovsdb_idl_row *row, + int64_t *in_pkts, int64_t *in_bytes, + int64_t *out_pkts, int64_t *out_bytes); + #endif //SRC_VNSW_AGENT_PHYSICAL_DEVICES_OVS_TOR_AGENT_OVSDB_CLIENT_OVSDB_WRAPPER_H_ diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc index 8857cf7d5a8..2a37dea868d 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.cc @@ -86,6 +86,11 @@ PhysicalPortEntry::ovs_binding_table() const { return ovs_binding_table_; } +const PhysicalPortEntry::VlanStatsTable & +PhysicalPortEntry::stats_table() const { + return stats_table_; +} + void PhysicalPortEntry::OverrideOvs() { struct ovsdb_idl_txn *txn = table_->client_idl()->CreateTxn(this); Encode(txn); @@ -147,6 +152,13 @@ void PhysicalPortTable::Notify(OvsdbClientIdl::Op op, entry->ovs_binding_table_[new_bind[i].vlan] = ls_entry; old.erase(new_bind[i].vlan); } + count = ovsdb_wrapper_physical_port_vlan_stats_count(row); + struct ovsdb_wrapper_port_vlan_stats stats[count]; + ovsdb_wrapper_physical_port_vlan_stats(row, stats); + entry->stats_table_.clear(); + for (std::size_t i = 0; i < count; i++) { + entry->stats_table_[stats[i].vlan] = stats[i].stats; + } PhysicalPortEntry::VlanLSTable::iterator it = old.begin(); for ( ; it != old.end(); it++) { if (entry->binding_table_.find(it->first) != @@ -198,6 +210,8 @@ class PhysicalPortSandeshTask : public Task { pentry.set_name(entry->name()); const PhysicalPortEntry::VlanLSTable &bindings = entry->ovs_binding_table(); + const PhysicalPortEntry::VlanStatsTable &stats_table = + entry->stats_table(); PhysicalPortEntry::VlanLSTable::const_iterator it = bindings.begin(); std::vector vlan_list; @@ -205,6 +219,22 @@ class PhysicalPortSandeshTask : public Task { OvsdbPhysicalPortVlanInfo vlan; vlan.set_vlan(it->first); vlan.set_logical_switch(it->second->name()); + PhysicalPortEntry::VlanStatsTable::const_iterator stats_it = + stats_table.find(it->first); + if (stats_it != stats_table.end()) { + int64_t in_pkts, in_bytes, out_pkts, out_bytes; + ovsdb_wrapper_get_logical_binding_stats(stats_it->second, + &in_pkts, &in_bytes, &out_pkts, &out_bytes); + vlan.set_in_pkts(in_pkts); + vlan.set_in_bytes(in_bytes); + vlan.set_out_pkts(out_pkts); + vlan.set_out_bytes(out_bytes); + } else { + vlan.set_in_pkts(0); + vlan.set_in_bytes(0); + vlan.set_out_pkts(0); + vlan.set_out_bytes(0); + } vlan_list.push_back(vlan); } pentry.set_vlans(vlan_list); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h index c7a4c21abc0..2f2cfb20cf5 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/physical_port_ovsdb.h @@ -23,6 +23,7 @@ class PhysicalPortTable : public OvsdbObject { class PhysicalPortEntry : public OvsdbEntry { public: typedef std::map VlanLSTable; + typedef std::map VlanStatsTable; PhysicalPortEntry(PhysicalPortTable *table, const char *name); PhysicalPortEntry(PhysicalPortTable *table, const std::string &name); ~PhysicalPortEntry(); @@ -36,6 +37,7 @@ class PhysicalPortEntry : public OvsdbEntry { const std::string &name() const; const VlanLSTable &ovs_binding_table() const; + const VlanStatsTable &stats_table() const; private: friend class PhysicalPortTable; @@ -44,6 +46,7 @@ class PhysicalPortEntry : public OvsdbEntry { struct ovsdb_idl_row *ovs_entry_; VlanLSTable binding_table_; VlanLSTable ovs_binding_table_; + VlanStatsTable stats_table_; DISALLOW_COPY_AND_ASSIGN(PhysicalPortEntry); }; }; From 9daf76340a0409b85a181bcbe75736463b0fff89 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Tue, 18 Nov 2014 08:50:56 +0530 Subject: [PATCH 211/218] Fix bug where vxlan id change was not getting reflected in multicast olist. Same was observed in change of address of TOR. Added support for both. --- src/vnsw/agent/controller/controller_peer.cc | 6 +- src/vnsw/agent/oper/multicast.cc | 314 +++++++++++++------ src/vnsw/agent/oper/multicast.h | 58 ++-- src/vnsw/agent/test/test_util.cc | 2 +- 4 files changed, 268 insertions(+), 112 deletions(-) diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index d6d49a30477..c0661cee4f4 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -380,7 +380,8 @@ void AgentXmppChannel::ReceiveMulticastUpdate(XmlPugi *pugi) { nh_label >> label; TunnelType::TypeBmap encap = GetMcastTypeBitmap(nh.tunnel_encapsulation_list); - olist.push_back(OlistTunnelEntry(label, addr.to_v4(), encap)); + olist.push_back(OlistTunnelEntry(nil_uuid(), label, + addr.to_v4(), encap)); } MulticastHandler::ModifyFabricMembers( @@ -602,7 +603,8 @@ void AgentXmppChannel::AddMulticastEvpnRoute(string vrf_name, int label = item->entry.olist.next_hop[i].label; TunnelType::TypeBmap encap = GetEnetTypeBitmap(item-> entry.olist.next_hop[i].tunnel_encapsulation_list); - olist.push_back(OlistTunnelEntry(label, addr.to_v4(), encap)); + olist.push_back(OlistTunnelEntry(nil_uuid(), label, + addr.to_v4(), encap)); } CONTROLLER_TRACE(Trace, GetBgpPeerName(), "Composite", diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index ea4875e0c46..567cac400a8 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -52,6 +52,10 @@ void MulticastHandler::Register() { agent_->device_manager()->physical_device_vn_table()-> Register(boost::bind(&MulticastHandler::ModifyTor, _1, _2)); + physical_device_listener_id_ = + agent_->device_manager()->device_table()-> + Register(boost::bind(&MulticastHandler::ModifyPhysicalDevice, + _1, _2)); } MulticastHandler::GetInstance()->GetMulticastObjList().clear(); @@ -85,11 +89,6 @@ void MulticastHandler::AddL2BroadcastRoute(MulticastGroupObject *obj, route_tunnel_bmap, Composite::L2INTERFACE, component_nh_key_list); - /* - RebakeSubnetRoute(agent_->local_vm_peer(), vrf_name, label, - vxlan_id, vn_name, false, - component_nh_key_list, Composite::L2INTERFACE); - */ } /* @@ -113,7 +112,7 @@ void MulticastHandler::HandleVxLanChange(const VnEntry *vn) { if (!obj || obj->IsDeleted()) return; - int new_vxlan_id = vn->GetVxLanId(); + uint32_t new_vxlan_id = vn->GetVxLanId(); if (new_vxlan_id != obj->vxlan_id()) { boost::system::error_code ec; @@ -159,64 +158,185 @@ void MulticastHandler::ModifyVN(DBTablePartBase *partition, DBEntryBase *e) MulticastHandler::GetInstance()->HandleIpam(vn); MulticastHandler::GetInstance()->HandleFamilyConfig(vn); - MulticastHandler::GetInstance()->HandleVxLanChange(vn); MulticastHandler::GetInstance()->HandleTor(vn); + MulticastHandler::GetInstance()->HandleVxLanChange(vn); +} + +bool IsTorDeleted(const PhysicalDeviceVnEntry *device_vn, + const PhysicalDeviceEntry *physical_device, + const VnEntry *vn, const VrfEntry *vrf) { + if (device_vn->IsDeleted() || !physical_device || !vn || !vrf) + return true; + + return false; } -void HandleTorRoute(const PhysicalDeviceVnEntry *device_vn, - const VnEntry *vn) +bool MulticastGroupObject::UpdateTorAddressInOlist(const uuid &device_uuid, + const Ip4Address &ip, + uint32_t vxlan_id) { + bool ret = false; + + for (std::vector::iterator it = tor_olist_.begin(); + it != tor_olist_.end(); it++) { + if ((*it).device_uuid_ == device_uuid) { + (*it).daddr_ = ip; + ret = true; + } + //All TOR have same vxlan in a VN. + if ((*it).label_ != vxlan_id) { + (*it).label_ = vxlan_id; + ret = true; + } + } + return ret; +} + +const OlistTunnelEntry *MulticastGroupObject::FindInTorListUsingUuid +(const uuid &device_uuid) { + for (std::vector::iterator it = tor_olist_.begin(); + it != tor_olist_.end(); it++) { + if ((*it).device_uuid_ == device_uuid) { + return &(*it); + } + } + return NULL; +} + +bool MulticastGroupObject::CanBeDeleted() const { + if (local_olist_.size() == 0 && tor_olist_.empty()) + return true; + return false; +} + +void DeleteTorFromAllMulticastObject(MulticastHandler *mc_handler, + const uuid &device_uuid) { - if (device_vn->vn() != vn) - return; + std::set &obj_list = + mc_handler->GetMulticastObjList(); + std::set deleted_obj_list; + for (std::set::iterator it = obj_list.begin(); + it != obj_list.end(); it++) { + MulticastGroupObject *obj = static_cast(*it); + boost::system::error_code ec; + Ip4Address null_ip = IpAddress::from_string("0.0.0.0", + ec).to_v4(); + bool deleted_tor = obj->DeleteFromTorList(device_uuid, + null_ip, + 0, 0, true); + if (!deleted_tor) + continue; - PhysicalDeviceEntry *physical_device = device_vn->device(); + if (obj->tor_olist().empty()) { + //Delete route path for TOR since olist is empty + Layer2AgentRouteTable::DeleteBroadcastReq(Agent::GetInstance()-> + multicast_tor_peer(), + obj->vrf_name(), + obj->vxlan_id()); + if (obj->CanBeDeleted()) { + MCTRACE(Log, "delete obj vrf/grp/size ", + obj->vrf_name(), obj->GetGroupAddress().to_string(), + mc_handler->GetMulticastObjList().size()); + delete (obj); + mc_handler->GetMulticastObjList().erase(it++); + } + continue; + } + + mc_handler->ModifyTorMembers(Agent::GetInstance()->multicast_tor_peer(), + obj->vrf_name(), + obj->tor_olist(), + obj->vxlan_id(), + 1); + } +} - uint32_t vxlan_id = vn->GetVxLanId(); +void HandleTorRoute(MulticastHandler *mc_handler, + const PhysicalDeviceVnEntry *device_vn_entry) +{ + const PhysicalDeviceEntry *physical_device = device_vn_entry->device(); + const VnEntry *device_vn = device_vn_entry->vn(); + const uuid &device_uuid = device_vn_entry->device_uuid(); + uint32_t vxlan_id = device_vn->GetVxLanId(); boost::system::error_code ec; Ip4Address addr = physical_device->ip().to_v4(); - MulticastGroupObject *obj = MulticastHandler::GetInstance()-> - FindFloodGroupObject(vn->GetVrf()->GetName()); - bool add_request = true; + const VrfEntry *device_vn_vrf = device_vn ? device_vn->GetVrf() : NULL; + bool rebake = false; + + //Get the multicast object + MulticastGroupObject *obj = NULL; + if (device_vn_vrf) + obj = mc_handler->FindFloodGroupObject(device_vn_vrf->GetName()); + + //Find out if physical device is deleted. + bool del_tor_request = IsTorDeleted(device_vn_entry, physical_device, + device_vn, device_vn_vrf); + if (del_tor_request) { + //May be VRF is gone from VN before we got the notification, + //so we may be blind to see where this device belonged. + //If device is deleted, walk all multicast objects to check + //for presence of this device and delete it. + if (!device_vn_vrf && device_vn_entry->IsDeleted()) { + DeleteTorFromAllMulticastObject(mc_handler, device_uuid); + return; + } - if (device_vn->IsDeleted()) { + //Deletion continues if vrf is known. + //Since there was no object, ignore physical device delete if (obj == NULL) return; - obj->DeleteFromTorList(addr, vxlan_id, TunnelType::VxlanType()); - if (obj->tor_olist().empty()) - add_request = false; - } - - if (!add_request) { - Layer2AgentRouteTable::DeleteBroadcastReq(Agent::GetInstance()-> - multicast_tor_peer(), - vn->GetVrf()->GetName(), - vxlan_id); - MulticastHandler::GetInstance()-> - DeleteMulticastObject(vn->GetVrf()->GetName(), addr); - return; - } - - if (add_request && (device_vn->IsDeleted() == false)) { - //TBD Make a common func to create object + obj->DeleteFromTorList(device_uuid, addr, vxlan_id, + TunnelType::VxlanType(), false); + if (obj->tor_olist().empty()) { + //Delete route path for TOR since olist is empty + Layer2AgentRouteTable::DeleteBroadcastReq(Agent::GetInstance()-> + multicast_tor_peer(), + device_vn_vrf->GetName(), + vxlan_id); + MulticastHandler::GetInstance()-> + DeleteMulticastObject(device_vn->GetVrf()->GetName(), addr); + return; + } + //Tor olist is not empty so fallback below to modify member list. + //Code is same for modification with add. + rebake = true; + } else { if (obj == NULL) { boost::system::error_code ec; Ip4Address broadcast = IpAddress::from_string("255.255.255.255", ec).to_v4(); obj = MulticastHandler::GetInstance()-> - CreateMulticastGroupObject(vn->GetVrf()->GetName(), + CreateMulticastGroupObject(device_vn->GetVrf()->GetName(), broadcast, - vn->GetName()); + device_vn->GetName(), + vxlan_id); } - obj->AddInTorList(addr, vxlan_id, TunnelType::VxlanType()); + rebake = obj->AddInTorList(device_uuid, addr, vxlan_id, + TunnelType::VxlanType()); } - MulticastHandler::ModifyTorMembers(Agent::GetInstance()-> - multicast_tor_peer(), - vn->GetVrf()->GetName(), - obj->tor_olist(), - vn->GetVxLanId(), - 1); + assert(obj != NULL); + + //rebake if VXLAN changed + if (vxlan_id != obj->vxlan_id()) { + obj->set_vxlan_id(vxlan_id); + rebake = true; + } + + //rebake if physical device address changed or any of the + //physical device has changed vxlan + rebake = obj->UpdateTorAddressInOlist(device_vn_entry->device_uuid(), + addr, + vxlan_id); + + if (rebake) { + MulticastHandler::ModifyTorMembers(Agent::GetInstance()-> + multicast_tor_peer(), + device_vn->GetVrf()->GetName(), + obj->tor_olist(), + device_vn->GetVxLanId(), + 1); + } } void MulticastHandler::ModifyTor(DBTablePartBase *partition, DBEntryBase *e) @@ -224,40 +344,53 @@ void MulticastHandler::ModifyTor(DBTablePartBase *partition, DBEntryBase *e) const PhysicalDeviceVnEntry *device_vn = static_cast(e); + HandleTorRoute(MulticastHandler::GetInstance(), device_vn); +} + +void MulticastHandler::ModifyPhysicalDevice(DBTablePartBase *partition, + DBEntryBase *e) +{ + MulticastHandler *handler = MulticastHandler::GetInstance(); + const PhysicalDeviceEntry *device = + static_cast(e); + //Take IP out of it - //PhysicalDeviceEntry *device = device_vn->device(); - VnEntry *vn = device_vn->vn(); - PhysicalDeviceEntry *physical_device = device_vn->device(); + const uuid &device_uuid = device->uuid(); + const IpAddress &ip = device->ip(); - if (!physical_device || !vn || !(vn->GetVrf())) - return; + handler->UpdatePhysicalDeviceAddressMap(device_uuid, ip); +} - if (vn->GetVrf() == NULL) { - return; +void MulticastHandler::UpdatePhysicalDeviceAddressMap(const uuid &device_uuid, + const IpAddress &ip) { + std::map::iterator it = + physical_device_uuid_addr_map_.find(device_uuid); + if ((it == physical_device_uuid_addr_map_.end()) || + (it->second != ip)) { + physical_device_uuid_addr_map_[device_uuid] = ip; + MulticastHandler::GetInstance()->HandleTor(NULL); } - HandleTorRoute(device_vn, vn); } -void MulticastHandler::WalkDone(const uuid &vn_uuid) { - std::map::iterator it = - physical_device_vn_walker_id_.find(vn_uuid); - if (it->second != DBTableWalker::kInvalidWalkerId) - physical_device_vn_walker_id_.erase(it); +void MulticastHandler::WalkDone() { + if (physical_device_vn_walker_id_ != DBTableWalker::kInvalidWalkerId) + physical_device_vn_walker_id_ = DBTableWalker::kInvalidWalkerId; } bool MulticastHandler::TorWalker(DBTablePartBase *partition, - DBEntryBase *entry, - const VnEntry *vn) { + DBEntryBase *entry) { PhysicalDeviceVnEntry *physical_vn_device = static_cast(entry); - HandleTorRoute(physical_vn_device, vn); + HandleTorRoute(this, physical_vn_device); return true; } void MulticastHandler::HandleTor(const VnEntry *vn) { - if (!vn->GetVrf()) + if (Agent::GetInstance()->tsn_enabled()) { return; + } + if ((Agent::GetInstance()->device_manager() == NULL) || (Agent::GetInstance()->device_manager()->physical_device_vn_table() == NULL)) { @@ -275,16 +408,17 @@ void MulticastHandler::HandleTor(const VnEntry *vn) walk_id = walker->WalkTable(Agent::GetInstance()->device_manager()-> physical_device_vn_table(), NULL, boost::bind(&MulticastHandler::TorWalker, this, _1, - _2, vn), - boost::bind(&MulticastHandler::WalkDone, this, - vn->GetUuid())); - physical_device_vn_walker_id_[vn->GetUuid()] = walk_id; + _2), + boost::bind(&MulticastHandler::WalkDone, this)); + physical_device_vn_walker_id_ = walk_id; } MulticastGroupObject *MulticastHandler::CreateMulticastGroupObject -(const string &vrf_name, const Ip4Address &ip_addr, const string &vn_name) { +(const string &vrf_name, const Ip4Address &ip_addr, const string &vn_name, + uint32_t vxlan_id) { MulticastGroupObject *obj = new MulticastGroupObject(vrf_name, ip_addr, vn_name); + obj->set_vxlan_id(vxlan_id); AddToMulticastObjList(obj); return obj; } @@ -401,8 +535,7 @@ void MulticastHandler::DeleteMulticastObject(const std::string &vrf_name, it != this->GetMulticastObjList().end(); it++) { if (((*it)->vrf_name() == vrf_name) && ((*it)->GetGroupAddress() == grp_addr)) { - if (((*it)->GetLocalListSize() != 0) || - !(((*it)->tor_olist()).empty())) + if (!((*it)->CanBeDeleted())) return; MCTRACE(Log, "delete obj vrf/grp/size ", vrf_name, grp_addr.to_string(), @@ -600,13 +733,11 @@ void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj, route_tunnel_bmap, comp_type, component_nh_key_list); - //if ((comp_type == Composite::EVPN) || (comp_type == Composite::TOR)) { - MCTRACE(Log, "rebake subnet peer for subnet", vrf_name, - "255.255.255.255", comp_type); - RebakeSubnetRoute(peer, obj->vrf_name(), label, obj->vxlan_id(), - obj->GetVnName(), false, component_nh_key_list, - comp_type); - //} + MCTRACE(Log, "rebake subnet peer for subnet", vrf_name, + "255.255.255.255", comp_type); + RebakeSubnetRoute(peer, obj->vrf_name(), label, obj->vxlan_id(), + obj->GetVnName(), false, component_nh_key_list, + comp_type); } void MulticastHandler::RebakeSubnetRoute(const Peer *peer, @@ -664,11 +795,10 @@ void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_itf) { all_broadcast = this->FindGroupObject(vrf_name, broadcast); if (all_broadcast == NULL) { all_broadcast = CreateMulticastGroupObject(vrf_name, broadcast, - vn_name); + vn_name, vn->GetVxLanId()); add_route = true; } - all_broadcast->set_vxlan_id(vn->GetVxLanId()); //Modify Nexthops if (all_broadcast->AddLocalMember(intf_uuid) == true) { if (vn->layer2_forwarding()) { @@ -797,10 +927,11 @@ void MulticastHandler::ModifyTorMembers(const Peer *peer, } const OlistTunnelEntry *MulticastGroupObject::FindInTorList -(const Ip4Address &ip_addr, uint32_t vxlan_id, uint32_t tunnel_bmap) { +(const uuid &device_uuid, uint32_t vxlan_id, uint32_t tunnel_bmap) { for (std::vector::iterator it = tor_olist_.begin(); it != tor_olist_.end(); it++) { - if (((*it).daddr_ == ip_addr) && ((*it).label_ == vxlan_id) && + if (((*it).device_uuid_ == device_uuid) && + ((*it).label_ == vxlan_id) && ((*it).tunnel_bmap_ == tunnel_bmap)) { return &(*it); } @@ -808,27 +939,34 @@ const OlistTunnelEntry *MulticastGroupObject::FindInTorList return NULL; } -void MulticastGroupObject::AddInTorList(const Ip4Address &ip_addr, +bool MulticastGroupObject::AddInTorList(const uuid &device_uuid, + const Ip4Address &ip_addr, uint32_t vxlan_id, uint32_t tunnel_bmap) { - if (FindInTorList(ip_addr, vxlan_id, tunnel_bmap)) - return; + if (FindInTorListUsingUuid(device_uuid) != NULL) + return false; - tor_olist_.push_back(OlistTunnelEntry(vxlan_id, ip_addr, + tor_olist_.push_back(OlistTunnelEntry(device_uuid, vxlan_id, ip_addr, tunnel_bmap)); + return true; } -void MulticastGroupObject::DeleteFromTorList(const Ip4Address &ip_addr, +bool MulticastGroupObject::DeleteFromTorList(const uuid &device_uuid, + const Ip4Address &ip_addr, uint32_t vxlan_id, - uint32_t tunnel_bmap) { + uint32_t tunnel_bmap, + bool use_uuid_only) { for (std::vector::iterator it = tor_olist_.begin(); it != tor_olist_.end(); it++) { - if (((*it).daddr_ == ip_addr) && ((*it).label_ == vxlan_id) && - ((*it).tunnel_bmap_ == tunnel_bmap)) { - tor_olist_.erase(it); - return; + if ((*it).device_uuid_ == device_uuid) { + if (use_uuid_only || (((*it).label_ == vxlan_id) && + ((*it).tunnel_bmap_ == tunnel_bmap))) { + tor_olist_.erase(it); + return true; + } } } + return false; } // Helper to delete fabric nh diff --git a/src/vnsw/agent/oper/multicast.h b/src/vnsw/agent/oper/multicast.h index f971602cd2f..fa198f9b293 100644 --- a/src/vnsw/agent/oper/multicast.h +++ b/src/vnsw/agent/oper/multicast.h @@ -25,12 +25,17 @@ do { ((grp.to_ulong() & 0xF0000000) == 0xE0000000)) struct OlistTunnelEntry { - OlistTunnelEntry() : label_(0), daddr_(0), tunnel_bmap_(0) { } - OlistTunnelEntry(uint32_t label, const Ip4Address &addr, + OlistTunnelEntry(const uuid &device_uuid, + uint32_t label, + const Ip4Address &addr, TunnelType::TypeBmap bmap) : - label_(label), daddr_(addr), tunnel_bmap_(bmap) { } + device_uuid_(device_uuid), + label_(label), + daddr_(addr), + tunnel_bmap_(bmap) { } virtual ~OlistTunnelEntry() { } + uuid device_uuid_; uint32_t label_; Ip4Address daddr_; TunnelType::TypeBmap tunnel_bmap_; @@ -62,6 +67,7 @@ class MulticastGroupObject { }; virtual ~MulticastGroupObject() { }; + bool CanBeDeleted() const; uint32_t evpn_mpls_label() const {return evpn_mpls_label_;} void set_evpn_mpls_label(uint32_t label) {evpn_mpls_label_ = label;} @@ -103,18 +109,25 @@ class MulticastGroupObject { bool layer2_forwarding() const {return layer2_forwarding_;}; void SetLayer2Forwarding(bool enable) {layer2_forwarding_ = enable;}; bool CanUnsubscribe() const {return (deleted_ || !layer2_forwarding_);} - void set_vxlan_id(int vxlan_id) {vxlan_id_ = vxlan_id;} - int vxlan_id() const {return vxlan_id_;} + void set_vxlan_id(uint32_t vxlan_id) {vxlan_id_ = vxlan_id;} + uint32_t vxlan_id() const {return vxlan_id_;} void set_peer_identifier(uint64_t peer_id) {peer_identifier_ = peer_id;} uint64_t peer_identifier() {return peer_identifier_;} - void AddInTorList(const Ip4Address &ip_addr, uint32_t vxlan_id, + bool AddInTorList(const uuid &device_uuid, + const Ip4Address &ip_addr, + uint32_t vxlan_id, uint32_t tunnel_bmap); - void DeleteFromTorList(const Ip4Address &ip_addr, uint32_t vxlan_id, - uint32_t tunnel_bmap); - const OlistTunnelEntry *FindInTorList(const Ip4Address &ip_addr, - uint32_t vxlan_id, - uint32_t tunnel_bmap); + bool DeleteFromTorList(const uuid &device_uuid, + const Ip4Address &ip_addr, uint32_t vxlan_id, + uint32_t tunnel_bmap, bool use_uuid_only); + const OlistTunnelEntry *FindInTorListUsingUuid(const uuid &device_uuid); + const OlistTunnelEntry *FindInTorList(const uuid &device_uuid, + uint32_t vxlan_id, + uint32_t tunnel_bmap); const TunnelOlist &tor_olist() const {return tor_olist_;} + bool UpdateTorAddressInOlist(const uuid &device_uuid, + const Ip4Address &ip, + uint32_t vxlan_id); private: @@ -123,7 +136,7 @@ class MulticastGroupObject { std::string vn_name_; Ip4Address src_address_; uint32_t evpn_mpls_label_; - int vxlan_id_; + uint32_t vxlan_id_; bool layer2_forwarding_; uint64_t peer_identifier_; bool deleted_; @@ -143,7 +156,8 @@ class MulticastHandler { MulticastGroupObject *CreateMulticastGroupObject(const string &vrf_name, const Ip4Address &ip_addr, - const string &vn_name); + const string &vn_name, + uint32_t vxlan_id); /* Called by XMPP to add ctrl node sent olist and label */ static void ModifyFabricMembers(const Peer *peer, @@ -167,10 +181,11 @@ class MulticastHandler { uint32_t ethernet_tag, uint64_t peer_identifier = 0); static void ModifyTor(DBTablePartBase *partition, DBEntryBase *e); + static void ModifyPhysicalDevice(DBTablePartBase *partition, DBEntryBase *e); + void UpdatePhysicalDeviceAddressMap(const uuid &uuid, const IpAddress &ip); void HandleTor(const VnEntry *vn); - void WalkDone(const uuid &vn_uuid); - bool TorWalker(DBTablePartBase *partition, DBEntryBase *entry, - const VnEntry *vn); + void WalkDone(); + bool TorWalker(DBTablePartBase *partition, DBEntryBase *entry); //Registered for VN notification static void ModifyVN(DBTablePartBase *partition, DBEntryBase *e); @@ -211,6 +226,9 @@ class MulticastHandler { MulticastGroupObject *FindFloodGroupObject(const std::string &vrf_name); MulticastGroupObject *FindActiveGroupObject(const std::string &vrf_name, const Ip4Address &dip); + std::set &GetMulticastObjList() { + return multicast_obj_list_; + }; MulticastGroupObject *FindGroupObject(const std::string &vrf_name, const Ip4Address &dip); ComponentNHKeyList GetInterfaceComponentNHKeyList(MulticastGroupObject *obj, @@ -230,10 +248,6 @@ class MulticastHandler { void AddToMulticastObjList(MulticastGroupObject *obj) { multicast_obj_list_.insert(obj); }; - std::set &GetMulticastObjList() { - return this->multicast_obj_list_; - }; - //VM intf add-delete void DeleteVmInterface(const Interface *intf); void AddVmInterfaceInFloodGroup(const VmInterface *vm_itf); @@ -282,7 +296,9 @@ class MulticastHandler { DBTable::ListenerId vn_listener_id_; DBTable::ListenerId interface_listener_id_; DBTable::ListenerId physical_device_vn_listener_id_;; - std::map physical_device_vn_walker_id_; + DBTable::ListenerId physical_device_listener_id_;; + DBTableWalker::WalkId physical_device_vn_walker_id_; + std::map physical_device_uuid_addr_map_; DISALLOW_COPY_AND_ASSIGN(MulticastHandler); }; diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 65998d76904..98326dcead1 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -2918,7 +2918,7 @@ void DeleteBgpPeer(Peer *peer) { void FillEvpnNextHop(BgpPeer *peer, std::string vrf_name, uint32_t label, uint32_t bmap) { TunnelOlist evpn_olist_map; - evpn_olist_map.push_back(OlistTunnelEntry(label, + evpn_olist_map.push_back(OlistTunnelEntry(nil_uuid(), label, IpAddress::from_string("8.8.8.8").to_v4(), bmap)); MulticastHandler::ModifyEvpnMembers(peer, vrf_name, From 7401adf94b49453544ebc1dc4c8ff32a55fbdc91 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 18 Nov 2014 02:25:56 -0800 Subject: [PATCH 212/218] change for tcp session to use non blocking socket fix post delete callback. adding introspect for other ovsdb tables. --- .../ovs_tor_agent/ovsdb_client/ovsdb.sandesh | 57 +++++++++++++ .../ovsdb_client/ovsdb_client_idl.cc | 15 ++++ .../ovsdb_client/ovsdb_client_idl.h | 3 + .../ovsdb_client/ovsdb_client_tcp.cc | 3 + .../ovs_tor_agent/ovsdb_client/ovsdb_entry.cc | 2 +- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 67 +++++++++++++++ .../ovsdb_client/unicast_mac_local_ovsdb.h | 5 ++ .../ovsdb_client/unicast_mac_remote_ovsdb.cc | 83 +++++++++++++++++++ .../ovsdb_client/unicast_mac_remote_ovsdb.h | 7 ++ .../ovsdb_client/vlan_port_binding_ovsdb.cc | 72 ++++++++++++++++ .../ovsdb_client/vlan_port_binding_ovsdb.h | 5 ++ 11 files changed, 318 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh index f3a9e2e1615..538ecbf955a 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb.sandesh @@ -120,10 +120,67 @@ traceobject sandesh OvsdbLogicalSwitch { 1: SandeshLogicalSwitchInfo l_switch; } +/**************************************************************************** + Sandesh definitions for Vlan Port Bindings. + ****************************************************************************/ + +struct OvsdbVlanPortBindingEntry { + 1: string state; + 2: string physical_port; + 3: string physical_device; + 4: string logical_switch; + 5: u16 vlan; +} + +response sandesh OvsdbVlanPortBindingResp { + 1: list bindings; +} + +request sandesh OvsdbVlanPortBindingReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} + +/**************************************************************************** + Sandesh definitions for Unicast Mac Local. + ****************************************************************************/ + +struct OvsdbUnicastMacLocalEntry { + 1: string state; + 2: string mac; + 3: string logical_switch; + 4: string dest_ip; +} + +response sandesh OvsdbUnicastMacLocalResp { + 1: list macs; +} + +request sandesh OvsdbUnicastMacLocalReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} + /**************************************************************************** Sandesh definitions for Unicast Mac Remote. ****************************************************************************/ +struct OvsdbUnicastMacRemoteEntry { + 1: string state; + 2: string mac; + 3: string logical_switch; + 4: string dest_ip; + 5: bool self_exported; +} + +response sandesh OvsdbUnicastMacRemoteResp { + 1: list macs; +} + +request sandesh OvsdbUnicastMacRemoteReq { + 1: string session_remote_ip; + 2: i16 session_remote_port; +} struct SandeshUnicastMacRemoteInfo { 1: string op; 2: string mac; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index ba1948cf2ee..3b85f24d7f9 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -44,6 +44,9 @@ using OVSDB::PhysicalSwitchTable; using OVSDB::LogicalSwitchTable; using OVSDB::PhysicalPortTable; using OVSDB::PhysicalLocatorTable; +using OVSDB::VlanPortBindingTable; +using OVSDB::UnicastMacLocalOvsdb; +using OVSDB::VrfOvsdbObject; namespace OVSDB { void ovsdb_wrapper_idl_callback(void *idl_base, int op, @@ -192,3 +195,15 @@ PhysicalLocatorTable *OvsdbClientIdl::physical_locator_table() { return physical_locator_table_.get(); } +VlanPortBindingTable *OvsdbClientIdl::vlan_port_table() { + return vlan_port_table_.get(); +} + +UnicastMacLocalOvsdb *OvsdbClientIdl::unicast_mac_local_ovsdb() { + return unicast_mac_local_ovsdb_.get(); +} + +VrfOvsdbObject *OvsdbClientIdl::vrf_ovsdb() { + return vrf_ovsdb_.get(); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 0e3103d63be..3512bad6f76 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -83,6 +83,9 @@ class OvsdbClientIdl { LogicalSwitchTable *logical_switch_table(); PhysicalPortTable *physical_port_table(); PhysicalLocatorTable *physical_locator_table(); + VlanPortBindingTable *vlan_port_table(); + UnicastMacLocalOvsdb *unicast_mac_local_ovsdb(); + VrfOvsdbObject *vrf_ovsdb(); private: friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc index 670c0fb4630..d069f5341df 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -41,6 +41,7 @@ TcpSession *OvsdbClientTcp::AllocSession(Socket *socket) { void OvsdbClientTcp::OnSessionEvent(TcpSession *session, TcpSession::Event event) { OvsdbClientTcpSession *tcp = static_cast(session); + boost::system::error_code ec; switch (event) { case TcpSession::CONNECT_FAILED: /* Failed to Connect, Try Again! */ @@ -52,6 +53,8 @@ void OvsdbClientTcp::OnSessionEvent(TcpSession *session, tcp->OnClose(); break; case TcpSession::CONNECT_COMPLETE: + ec = tcp->SetSocketOptions(); + assert(ec.value() == 0); tcp->set_status("Established"); tcp->OnEstablish(); break; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc index 13b42c3bf33..b4be56e53a4 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_entry.cc @@ -82,11 +82,11 @@ bool OvsdbDBEntry::Change() { } bool OvsdbDBEntry::Delete() { - PostDelete(); OvsdbDBObject *object = static_cast(GetObject()); struct ovsdb_idl_txn *txn = object->client_idl_->CreateTxn(this); DeleteMsg(txn); struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn); + PostDelete(); if (msg == NULL) { object->client_idl()->DeleteTxn(txn); return true; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index 01ec796458f..c9593c69b47 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -5,6 +5,10 @@ extern "C" { #include }; +#include +#include +#include +#include #include #include #include @@ -15,6 +19,7 @@ extern "C" { using OVSDB::UnicastMacLocalOvsdb; using OVSDB::UnicastMacLocalEntry; +using OVSDB::OvsdbClientSession; using std::string; UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table, @@ -76,6 +81,18 @@ KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() { return NULL; } +const std::string &UnicastMacLocalEntry::mac() const { + return mac_; +} + +const std::string &UnicastMacLocalEntry::logical_switch_name() const { + return logical_switch_name_; +} + +const std::string &UnicastMacLocalEntry::dest_ip() const { + return dest_ip_; +} + UnicastMacLocalOvsdb::UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer) : OvsdbObject(idl), peer_(peer) { idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL, @@ -122,3 +139,53 @@ KSyncEntry *UnicastMacLocalOvsdb::Alloc(const KSyncEntry *key, uint32_t index) { return entry; } +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class UnicastMacLocalSandeshTask : public Task { +public: + UnicastMacLocalSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbUnicastMacLocalResp()), resp_data_(resp_ctx) { + } + virtual ~UnicastMacLocalSandeshTask() {} + virtual bool Run() { + std::vector macs; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + UnicastMacLocalOvsdb *table = + session->client_idl()->unicast_mac_local_ovsdb(); + UnicastMacLocalEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbUnicastMacLocalEntry oentry; + oentry.set_state(entry->StateString()); + oentry.set_mac(entry->mac()); + oentry.set_logical_switch(entry->logical_switch_name()); + oentry.set_dest_ip(entry->dest_ip()); + macs.push_back(oentry); + entry = static_cast(table->Next(entry)); + } + resp_->set_macs(macs); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbUnicastMacLocalResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalSandeshTask); +}; + +void OvsdbUnicastMacLocalReq::HandleRequest() const { + UnicastMacLocalSandeshTask *task = new UnicastMacLocalSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h index 98b1d0d7d90..29e56098dd8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.h @@ -37,6 +37,11 @@ class UnicastMacLocalEntry : public OvsdbEntry { bool IsLess(const KSyncEntry&) const; KSyncEntry* UnresolvedReference(); std::string ToString() const {return "Unicast Mac Local";} + + const std::string &mac() const; + const std::string &logical_switch_name() const; + const std::string &dest_ip() const; + private: friend class UnicastMacLocalOvsdb; std::string mac_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index 6db4d9bba8c..03575b84b1e 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -5,6 +5,10 @@ extern "C" { #include }; +#include +#include +#include +#include #include #include #include @@ -23,6 +27,7 @@ using OVSDB::UnicastMacRemoteTable; using OVSDB::VrfOvsdbObject; using OVSDB::OvsdbDBEntry; using OVSDB::OvsdbDBObject; +using OVSDB::OvsdbClientSession; UnicastMacRemoteEntry::UnicastMacRemoteEntry(OvsdbDBObject *table, const std::string mac, const std::string logical_switch) : @@ -166,6 +171,22 @@ KSyncEntry *UnicastMacRemoteEntry::UnresolvedReference() { return NULL; } +const std::string &UnicastMacRemoteEntry::mac() const { + return mac_; +} + +const std::string &UnicastMacRemoteEntry::logical_switch_name() const { + return logical_switch_name_; +} + +const std::string &UnicastMacRemoteEntry::dest_ip() const { + return dest_ip_; +} + +bool UnicastMacRemoteEntry::self_exported_route() const { + return self_exported_route_; +} + void UnicastMacRemoteEntry::SendTrace(Trace event) const { SandeshUnicastMacRemoteInfo info; switch (event) { @@ -353,3 +374,65 @@ void VrfOvsdbObject::VrfNotify(DBTablePartBase *partition, DBEntryBase *e) { } } +const VrfOvsdbObject::LogicalSwitchMap & +VrfOvsdbObject::logical_switch_map() const { + return logical_switch_map_; +} + +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class UnicastMacRemoteSandeshTask : public Task { +public: + UnicastMacRemoteSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbUnicastMacRemoteResp()), resp_data_(resp_ctx) { + } + virtual ~UnicastMacRemoteSandeshTask() {} + virtual bool Run() { + std::vector macs; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + VrfOvsdbObject *vrf_obj = session->client_idl()->vrf_ovsdb(); + const VrfOvsdbObject::LogicalSwitchMap ls_table = + vrf_obj->logical_switch_map(); + VrfOvsdbObject::LogicalSwitchMap::const_iterator it = ls_table.begin(); + for (; it != ls_table.end(); it++) { + UnicastMacRemoteTable *table = it->second->l2_table; + UnicastMacRemoteEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbUnicastMacRemoteEntry oentry; + oentry.set_state(entry->StateString()); + oentry.set_mac(entry->mac()); + oentry.set_logical_switch(entry->logical_switch_name()); + oentry.set_dest_ip(entry->dest_ip()); + oentry.set_self_exported(entry->self_exported_route()); + macs.push_back(oentry); + entry = static_cast(table->Next(entry)); + } + } + resp_->set_macs(macs); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbUnicastMacRemoteResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(UnicastMacRemoteSandeshTask); +}; + +void OvsdbUnicastMacRemoteReq::HandleRequest() const { + UnicastMacRemoteSandeshTask *task = + new UnicastMacRemoteSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h index 0c431a9a7c6..5dae50a4974 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -66,6 +66,11 @@ class UnicastMacRemoteEntry : public OvsdbDBEntry { std::string ToString() const {return "Unicast Mac Remote";} KSyncEntry* UnresolvedReference(); + const std::string &mac() const; + const std::string &logical_switch_name() const; + const std::string &dest_ip() const; + bool self_exported_route() const; + private: friend class UnicastMacRemoteTable; friend class VrfOvsdbObject; @@ -92,6 +97,8 @@ class VrfOvsdbObject { void OvsdbRouteNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *); void VrfNotify(DBTablePartBase *partition, DBEntryBase *e); + const LogicalSwitchMap &logical_switch_map() const; + private: OvsdbClientIdl *client_idl_; DBTable *table_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc index 3f7056c7272..9bda710af64 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.cc @@ -5,6 +5,10 @@ extern "C" { #include }; +#include +#include +#include +#include #include #include #include @@ -25,6 +29,7 @@ using OVSDB::VlanPortBindingTable; using OVSDB::PhysicalSwitchEntry; using OVSDB::PhysicalPortEntry; using OVSDB::LogicalSwitchEntry; +using OVSDB::OvsdbClientSession; VlanPortBindingEntry::VlanPortBindingEntry(VlanPortBindingTable *table, const AGENT::VlanLogicalPortEntry *entry) : OvsdbDBEntry(table_), @@ -194,6 +199,22 @@ KSyncEntry *VlanPortBindingEntry::UnresolvedReference() { return NULL; } +const std::string &VlanPortBindingEntry::logical_switch_name() const { + return logical_switch_name_; +} + +const std::string &VlanPortBindingEntry::physical_port_name() const { + return physical_port_name_; +} + +const std::string &VlanPortBindingEntry::physical_device_name() const { + return physical_device_name_; +} + +uint16_t VlanPortBindingEntry::vlan() const { + return vlan_; +} + VlanPortBindingTable::VlanPortBindingTable(OvsdbClientIdl *idl, DBTable *table) : OvsdbDBObject(idl, table) { } @@ -242,3 +263,54 @@ KSyncDBObject::DBFilterResp VlanPortBindingTable::DBEntryFilter( return DBFilterAccept; } +///////////////////////////////////////////////////////////////////////////// +// Sandesh routines +///////////////////////////////////////////////////////////////////////////// +class VlanPortBindingSandeshTask : public Task { +public: + VlanPortBindingSandeshTask(std::string resp_ctx) : + Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1), + resp_(new OvsdbVlanPortBindingResp()), resp_data_(resp_ctx) { + } + virtual ~VlanPortBindingSandeshTask() {} + virtual bool Run() { + std::vector bindings; + TorAgentInit *init = + static_cast(Agent::GetInstance()->agent_init()); + OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL); + VlanPortBindingTable *table = + session->client_idl()->vlan_port_table(); + VlanPortBindingEntry *entry = + static_cast(table->Next(NULL)); + while (entry != NULL) { + OvsdbVlanPortBindingEntry oentry; + oentry.set_state(entry->StateString()); + oentry.set_physical_port(entry->physical_port_name()); + oentry.set_physical_device(entry->physical_device_name()); + oentry.set_logical_switch(entry->logical_switch_name()); + oentry.set_vlan(entry->vlan()); + bindings.push_back(oentry); + entry = static_cast(table->Next(entry)); + } + resp_->set_bindings(bindings); + SendResponse(); + return true; + } +private: + void SendResponse() { + resp_->set_context(resp_data_); + resp_->set_more(false); + resp_->Response(); + } + + OvsdbVlanPortBindingResp *resp_; + std::string resp_data_; + DISALLOW_COPY_AND_ASSIGN(VlanPortBindingSandeshTask); +}; + +void OvsdbVlanPortBindingReq::HandleRequest() const { + VlanPortBindingSandeshTask *task = new VlanPortBindingSandeshTask(context()); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Enqueue(task); +} + diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h index 637b46654cd..4eb9a33aa54 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/vlan_port_binding_ovsdb.h @@ -46,6 +46,11 @@ class VlanPortBindingEntry : public OvsdbDBEntry { std::string ToString() const {return "Vlan Port Binding";} KSyncEntry* UnresolvedReference(); + const std::string &logical_switch_name() const; + const std::string &physical_port_name() const; + const std::string &physical_device_name() const; + uint16_t vlan() const; + private: friend class VlanPortBindingTable; KSyncEntryPtr logical_switch_; From 6c7b6cba35ffbf029b5af26b35da5672c360e79e Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Tue, 18 Nov 2014 23:48:30 -0800 Subject: [PATCH 213/218] Fix message parsing if multiple json messages are received in single read. adding Ovsdb Pkt trace. --- .../ovsdb_client/ovsdb_client_idl.cc | 68 +++++++++++-------- .../ovsdb_client/ovsdb_client_idl.h | 7 ++ .../ovsdb_client/ovsdb_client_tcp.cc | 2 + 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 3b85f24d7f9..7d191a73c3f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -28,6 +28,7 @@ extern "C" { #include SandeshTraceBufferPtr OvsdbTraceBuf(SandeshTraceBufferCreate("Ovsdb", 5000)); +SandeshTraceBufferPtr OvsdbPktTraceBuf(SandeshTraceBufferCreate("Ovsdb Pkt", 5000)); namespace AGENT { class PhysicalDeviceTable; @@ -119,36 +120,47 @@ void OvsdbClientIdl::SendJsonRpc(struct jsonrpc_msg *msg) { } void OvsdbClientIdl::MessageProcess(const u_int8_t *buf, std::size_t len) { - if (parser_ == NULL) { - parser_ = ovsdb_wrapper_json_parser_create(0); - } - ovsdb_wrapper_json_parser_feed(parser_, (const char *)buf, len); - - /* If we have complete JSON, attempt to parse it as JSON-RPC. */ - if (ovsdb_wrapper_json_parser_is_done(parser_)) { - struct json *json = ovsdb_wrapper_json_parser_finish(parser_); - parser_ = NULL; - struct jsonrpc_msg *msg; - char *error = ovsdb_wrapper_jsonrpc_msg_from_json(json, &msg); - if (error) { - free(error); - assert(0); - //return; + std::size_t used = 0; + // Multiple json message may be clubbed together, need to keep reading + // the buffer till whole message is consumed. + while (used != len) { + if (parser_ == NULL) { + parser_ = ovsdb_wrapper_json_parser_create(0); } - - if (ovsdb_wrapper_msg_echo_req(msg)) { - /* Echo request. Send reply. */ - struct jsonrpc_msg *reply; - reply = ovsdb_wrapper_jsonrpc_create_reply(msg); - SendJsonRpc(reply); - //jsonrpc_session_send(s, reply); - } else if (ovsdb_wrapper_msg_echo_reply(msg)) { - /* It's a reply to our echo request. Suppress it. */ - } else { - ovsdb_wrapper_idl_msg_process(idl_, msg); - return; + const u_int8_t *pkt = buf + used; + std::size_t pkt_len = len - used; + std::size_t read; + read = ovsdb_wrapper_json_parser_feed(parser_, (const char *)pkt, + pkt_len); + OVSDB_PKT_TRACE(Trace, "Processed: " + std::string((const char *)pkt, read)); + used +=read; + + /* If we have complete JSON, attempt to parse it as JSON-RPC. */ + if (ovsdb_wrapper_json_parser_is_done(parser_)) { + struct json *json = ovsdb_wrapper_json_parser_finish(parser_); + parser_ = NULL; + struct jsonrpc_msg *msg; + char *error = ovsdb_wrapper_jsonrpc_msg_from_json(json, &msg); + if (error) { + assert(0); + free(error); + //continue; + } + + if (ovsdb_wrapper_msg_echo_req(msg)) { + /* Echo request. Send reply. */ + struct jsonrpc_msg *reply; + reply = ovsdb_wrapper_jsonrpc_create_reply(msg); + SendJsonRpc(reply); + //jsonrpc_session_send(s, reply); + } else if (ovsdb_wrapper_msg_echo_reply(msg)) { + /* It's a reply to our echo request. Suppress it. */ + } else { + ovsdb_wrapper_idl_msg_process(idl_, msg); + continue; + } + ovsdb_wrapper_jsonrpc_msg_destroy(msg); } - ovsdb_wrapper_jsonrpc_msg_destroy(msg); } } diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index 3512bad6f76..955a85720a8 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -12,11 +12,18 @@ #include extern SandeshTraceBufferPtr OvsdbTraceBuf; +extern SandeshTraceBufferPtr OvsdbPktTraceBuf; + #define OVSDB_TRACE(obj, ...)\ do {\ Ovsdb##obj::TraceMsg(OvsdbTraceBuf, __FILE__, __LINE__, __VA_ARGS__);\ } while(false); +#define OVSDB_PKT_TRACE(obj, ...)\ +do {\ + Ovsdb##obj::TraceMsg(OvsdbPktTraceBuf, __FILE__, __LINE__, __VA_ARGS__);\ +} while(false); + class OvsPeer; class OvsPeerManager; class KSyncObjectManager; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc index d069f5341df..f594c17c534 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_client_tcp.cc @@ -119,10 +119,12 @@ void OvsdbClientTcpSession::OnRead(Buffer buffer) { } void OvsdbClientTcpSession::SendMsg(u_int8_t *buf, std::size_t len) { + OVSDB_PKT_TRACE(Trace, "Sending: " + std::string((char *)buf, len)); Send(buf, len, NULL); } void OvsdbClientTcpSession::RecvMsg(const u_int8_t *buf, std::size_t len) { + OVSDB_PKT_TRACE(Trace, "Received: " + std::string((const char*)buf, len)); queue_msg msg; msg.buf = (u_int8_t *)malloc(len); memcpy(msg.buf, buf, len); From a0f35461f9e3feddaa5c9a2359432de87eaa27db Mon Sep 17 00:00:00 2001 From: manishsingh Date: Thu, 20 Nov 2014 10:50:27 +0530 Subject: [PATCH 214/218] Fix the check of tsn_enabled. --- src/vnsw/agent/oper/multicast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index 567cac400a8..c599aa5b4ac 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -387,7 +387,7 @@ bool MulticastHandler::TorWalker(DBTablePartBase *partition, void MulticastHandler::HandleTor(const VnEntry *vn) { - if (Agent::GetInstance()->tsn_enabled()) { + if (Agent::GetInstance()->tsn_enabled() == false) { return; } From cd717745cfb54779f6f2de3221aa164a6eab479b Mon Sep 17 00:00:00 2001 From: Hari Date: Thu, 20 Nov 2014 01:25:29 -0800 Subject: [PATCH 215/218] bug fixes: initialize configurer variable, remove interface reference, init uve --- src/vnsw/agent/oper/vm_interface.cc | 4 +- src/vnsw/agent/oper/vn.cc | 16 +++++-- src/vnsw/agent/oper/vn.h | 1 + src/vnsw/agent/pkt/pkt_handler.cc | 42 +++++++++++++------ src/vnsw/agent/pkt/pkt_handler.h | 17 ++++---- src/vnsw/agent/uve/agent_uve_base.cc | 2 +- .../linux/linux_vxlan_agent_init.cc | 2 + 7 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 8f6f14ff95e..4a73a493893 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -57,7 +57,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) : sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(), - sub_type_(VmInterface::NONE), ifmap_node_(NULL) { + sub_type_(VmInterface::NONE), configurer_(0), ifmap_node_(NULL) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; @@ -83,7 +83,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid, sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(), allowed_address_pair_list_(), vrf_assign_rule_list_(), vrf_assign_acl_(NULL), sub_type_(VmInterface::NONE), - ifmap_node_(NULL) { + configurer_(0), ifmap_node_(NULL) { ipv4_active_ = false; ipv6_active_ = false; l2_active_ = false; diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index b9a9ac6361a..25eef149c12 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -690,8 +690,10 @@ bool VnTable::IpamChangeNotify(std::vector &old_ipam, // If gateway is changed then take appropriate actions. IpAddress unspecified; if (gateway_changed) { - UpdateHostRoute((*it_old).default_gw, - (*it_new).default_gw, vn); + if (IsGwHostRouteRequired()) { + UpdateHostRoute((*it_old).default_gw, + (*it_new).default_gw, vn); + } } if (service_address_changed) { UpdateHostRoute((*it_old).dns_server, @@ -754,7 +756,8 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { if (vrf->GetName() == Agent::GetInstance()->linklocal_vrf_name()) { return; } - AddHostRoute(vn, ipam.default_gw); + if (IsGwHostRouteRequired()) + AddHostRoute(vn, ipam.default_gw); AddHostRoute(vn, ipam.dns_server); AddSubnetRoute(vn, ipam); ipam.installed = true; @@ -764,13 +767,18 @@ void VnTable::AddIPAMRoutes(VnEntry *vn, VnIpam &ipam) { void VnTable::DelIPAMRoutes(VnEntry *vn, VnIpam &ipam) { VrfEntry *vrf = vn->GetVrf(); if (vrf && ipam.installed) { - DelHostRoute(vn, ipam.default_gw); + if (IsGwHostRouteRequired()) + DelHostRoute(vn, ipam.default_gw); DelHostRoute(vn, ipam.dns_server); DelSubnetRoute(vn, ipam); ipam.installed = false; } } +bool VnTable::IsGwHostRouteRequired() { + return (!agent()->tsn_enabled()); +} + // Add receive route for default gw void VnTable::AddHostRoute(VnEntry *vn, const IpAddress &address) { VrfEntry *vrf = vn->GetVrf(); diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index 7c3bda69c95..541234d1214 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -260,6 +260,7 @@ class VnTable : public AgentDBTable { void DeleteAllIpamRoutes(VnEntry *vn); void AddSubnetRoute(VnEntry *vn, VnIpam &ipam); void DelSubnetRoute(VnEntry *vn, VnIpam &ipam); + bool IsGwHostRouteRequired(); void AddHostRoute(VnEntry *vn, const IpAddress &address); void DelHostRoute(VnEntry *vn, const IpAddress &address); bool ChangeHandler(DBEntry *entry, const DBRequest *req); diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index 2eac1e197e3..a09c66f1982 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -71,7 +71,7 @@ void PktHandler::InterfaceNotify(DBEntryBase *entry) { return; const VmInterface *vmitf = static_cast(entry); - if (vmitf->vm_mac().empty() || !vmitf->vn()) + if (vmitf->vm_mac().empty()) return; boost::system::error_code ec; @@ -79,16 +79,34 @@ void PktHandler::InterfaceNotify(DBEntryBase *entry) { if (ec) { return; } - MacVmBindingKey key(address, vmitf->vn()->GetVxLanId()); - if (entry->IsDeleted()) { - mac_vm_binding_map_.erase(key); - } else { - // assumed that VM mac and VN's vxlan id do not change - mac_vm_binding_map_.insert(MacVmBindingPair(key, itf)); + MacVmBindingSet::iterator it = FindMacVmBinding(address, itf); + if (it != mac_vm_binding_.end()) + mac_vm_binding_.erase(it); + + if (!entry->IsDeleted()) { + if (!vmitf->vn() || vmitf->vn()->GetVxLanId() == 0) { + return; + } + // assumed that VM mac does not change + MacVmBindingKey key(address, vmitf->vn()->GetVxLanId(), itf); + mac_vm_binding_.insert(key); } } +PktHandler::MacVmBindingSet::iterator +PktHandler::FindMacVmBinding(MacAddress &address, const Interface *interface) { + MacVmBindingSet::iterator it = + mac_vm_binding_.lower_bound(MacVmBindingKey(address, 0, NULL)); + while (it != mac_vm_binding_.end()) { + if (it->interface == interface) + return it; + it++; + } + + return it; +} + void PktHandler::Register(PktModuleName type, RcvQueueFunc cb) { enqueue_cb_.at(type) = cb; } @@ -534,17 +552,17 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, ether_addr addr; memcpy(addr.ether_addr_octet, pkt_info->eth->ether_shost, ETH_ALEN); MacAddress address(addr); - MacVmBindingKey key(address, vxlan); - MacVmBindingMap::iterator it = mac_vm_binding_map_.find(key); - if (it == mac_vm_binding_map_.end()) + MacVmBindingKey key(address, vxlan, NULL); + MacVmBindingSet::iterator it = mac_vm_binding_.find(key); + if (it == mac_vm_binding_.end()) return false; // update agent_hdr to reflect the VM interface data // cmd_param is set to physical interface id pkt_info->agent_hdr.cmd = AgentHdr::TRAP_TOR_CONTROL_PKT; pkt_info->agent_hdr.cmd_param = pkt_info->agent_hdr.ifindex; - pkt_info->agent_hdr.ifindex = it->second->id(); - pkt_info->agent_hdr.vrf = it->second->vrf_id(); + pkt_info->agent_hdr.ifindex = it->interface->id(); + pkt_info->agent_hdr.vrf = it->interface->vrf_id(); // Parse payload if (pkt_info->ether_type == ETHERTYPE_ARP) { diff --git a/src/vnsw/agent/pkt/pkt_handler.h b/src/vnsw/agent/pkt/pkt_handler.h index cde6fb6d0e6..b0f159db57b 100644 --- a/src/vnsw/agent/pkt/pkt_handler.h +++ b/src/vnsw/agent/pkt/pkt_handler.h @@ -262,17 +262,18 @@ class PktHandler { struct MacVmBindingKey { MacAddress mac; int vxlan; + InterfaceConstRef interface; - MacVmBindingKey(MacAddress &m, int v) : mac(m), vxlan(v) {} + MacVmBindingKey(MacAddress &m, int v, InterfaceConstRef intf) : + mac(m), vxlan(v), interface(intf) {} bool operator<(const MacVmBindingKey &rhs) const { - if (vxlan != rhs.vxlan) - return vxlan < rhs.vxlan; + if (mac != rhs.mac) + return mac < rhs.mac; - return mac < rhs.mac; + return vxlan < rhs.vxlan; } }; - typedef std::map MacVmBindingMap; - typedef std::pair MacVmBindingPair; + typedef std::set MacVmBindingSet; void InterfaceNotify(DBEntryBase *entry); uint8_t *ParseEthernetHeader(PktInfo *pkt_info, @@ -288,6 +289,8 @@ class PktHandler { bool IsValidInterface(uint16_t ifindex, Interface **interface); bool IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, PktType::Type &pkt_type, uint8_t *pkt); + MacVmBindingSet::iterator + FindMacVmBinding(MacAddress &address, const Interface *interface); // handlers for each module type boost::array enqueue_cb_; @@ -297,7 +300,7 @@ class PktHandler { // map of VM mac addresses to VM Interface, used in TOR services node // to identify the VM based on incoming packet's mac address. - MacVmBindingMap mac_vm_binding_map_; + MacVmBindingSet mac_vm_binding_; DBTableBase::ListenerId iid_; Agent *agent_; diff --git a/src/vnsw/agent/uve/agent_uve_base.cc b/src/vnsw/agent/uve/agent_uve_base.cc index f0c1e34b191..4f62207ef57 100644 --- a/src/vnsw/agent/uve/agent_uve_base.cc +++ b/src/vnsw/agent/uve/agent_uve_base.cc @@ -78,7 +78,7 @@ uint8_t AgentUveBase::ExpectedConnections(uint8_t &num_control_nodes, num_control_nodes++; count++; } - if (!agent_->dns_server(i).empty()) { + if (agent_->services() && !agent_->dns_server(i).empty()) { num_dns_servers++; count++; } diff --git a/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc b/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc index b11d54ec621..8d7e8fb7ac1 100644 --- a/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc +++ b/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc @@ -75,10 +75,12 @@ void LinuxVxlanAgentInit::CreateModules() { void LinuxVxlanAgentInit::RegisterDBClients() { ksync_vxlan_->RegisterDBClients(agent()->db()); + uve_->RegisterDBClients(); } void LinuxVxlanAgentInit::InitModules() { ksync_vxlan_->Init(); + uve_->Init(); } void LinuxVxlanAgentInit::ConnectToController() { From 8bc4e1af84fd138d77651aae74189463641b5839 Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Thu, 20 Nov 2014 01:52:32 -0800 Subject: [PATCH 216/218] Issue: vrf delete timeout, Find of deleted VN fails and OVS fails to remove exported route path. Fix: while deleting the exported route path use direct reference instead of find. --- .../ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc | 8 +------- .../ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h | 3 +-- .../ovsdb_client/unicast_mac_local_ovsdb.cc | 10 ++++++++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc index 7ee0fea1a21..87cb67fd330 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc @@ -53,13 +53,7 @@ bool OvsPeer::AddOvsRoute(const boost::uuids::uuid &vn_uuid, return true; } -bool OvsPeer::DeleteOvsRoute(const boost::uuids::uuid &vn_uuid, - const MacAddress &mac) { - Agent *agent = peer_manager_->agent(); - VnEntry *vn = agent->vn_table()->Find(vn_uuid); - if (vn == NULL) - return false; - +bool OvsPeer::DeleteOvsRoute(const VnEntry *vn, const MacAddress &mac) { VrfEntry *vrf = vn->GetVrf(); if (vrf == NULL) return false; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h index 8ec695db8f7..427d669312f 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.h @@ -19,8 +19,7 @@ class OvsPeer : public Peer { const Ip4Address *NexthopIp(Agent *agent, const AgentPath *path) const; bool AddOvsRoute(const boost::uuids::uuid &vn_uuid, const MacAddress &mac, Ip4Address &tor_ip); - bool DeleteOvsRoute(const boost::uuids::uuid &vn_uuid, - const MacAddress &mac); + bool DeleteOvsRoute(const VnEntry *vn, const MacAddress &mac); private: IpAddress peer_ip_; uint64_t gen_id_; diff --git a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc index c9593c69b47..c75c962c736 100644 --- a/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc +++ b/src/vnsw/agent/physical_devices/ovs_tor_agent/ovsdb_client/unicast_mac_local_ovsdb.cc @@ -5,7 +5,9 @@ extern "C" { #include }; +#include #include +#include #include #include #include @@ -17,6 +19,7 @@ extern "C" { #include #include +using namespace AGENT; using OVSDB::UnicastMacLocalOvsdb; using OVSDB::UnicastMacLocalEntry; using OVSDB::OvsdbClientSession; @@ -57,8 +60,11 @@ bool UnicastMacLocalEntry::Delete() { UnicastMacLocalOvsdb *table = static_cast(table_); OVSDB_TRACE(Trace, "Deleting Route " + mac_ + " VN uuid " + logical_switch_name_ + " destination IP " + dest_ip_); - boost::uuids::uuid ls_uuid = StringToUuid(logical_switch_name_); - table->peer()->DeleteOvsRoute(ls_uuid, MacAddress(mac_)); + LogicalSwitchEntry *ls_entry = + static_cast(logical_switch_.get()); + const PhysicalDeviceVnEntry *dev_vn = + static_cast(ls_entry->GetDBEntry()); + table->peer()->DeleteOvsRoute(dev_vn->vn(), MacAddress(mac_)); return true; } From cd77a94e235ecfcd7b5419d770d8c87a7ab073d0 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Thu, 20 Nov 2014 14:45:25 +0530 Subject: [PATCH 217/218] Delete subnet route whenever L2 route path is deleted. --- src/vnsw/agent/oper/multicast.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index c599aa5b4ac..5db7933075d 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -232,6 +232,12 @@ void DeleteTorFromAllMulticastObject(MulticastHandler *mc_handler, multicast_tor_peer(), obj->vrf_name(), obj->vxlan_id()); + ComponentNHKeyList component_nh_key_list; //dummy list + mc_handler->RebakeSubnetRoute(Agent::GetInstance()->multicast_tor_peer(), + obj->vrf_name(), 0, obj->vxlan_id(), + obj ? obj->GetVnName() : "", + true, component_nh_key_list, + Composite::TOR); if (obj->CanBeDeleted()) { MCTRACE(Log, "delete obj vrf/grp/size ", obj->vrf_name(), obj->GetGroupAddress().to_string(), @@ -292,6 +298,11 @@ void HandleTorRoute(MulticastHandler *mc_handler, multicast_tor_peer(), device_vn_vrf->GetName(), vxlan_id); + ComponentNHKeyList component_nh_key_list; //dummy list + mc_handler->RebakeSubnetRoute(Agent::GetInstance()->multicast_tor_peer(), + device_vn_vrf->GetName(), 0, vxlan_id, "", + true, component_nh_key_list, + Composite::TOR); MulticastHandler::GetInstance()-> DeleteMulticastObject(device_vn->GetVrf()->GetName(), addr); return; @@ -749,6 +760,10 @@ void MulticastHandler::RebakeSubnetRoute(const Peer *peer, const ComponentNHKeyList &comp_nh_list, COMPOSITETYPE comp_type) { + if (peer->GetType() != Peer::MULTICAST_TOR_PEER && + peer->GetType() != Peer::BGP_PEER) { + return; + } std::vector &vrf_ipam = (vrf_ipam_mapping_.find(vrf_name))->second; for (std::vector::iterator it = vrf_ipam.begin(); From 461bec22ced5b4a8e82efdb5fcffaf16576cddf2 Mon Sep 17 00:00:00 2001 From: manishsingh Date: Sat, 22 Nov 2014 13:17:20 +0530 Subject: [PATCH 218/218] For subnet route delete all multicast paths from route if local_peer path is gone as it happens when IPAM is gone. --- src/vnsw/agent/oper/agent_route.cc | 15 +++++++++++++++ src/vnsw/agent/oper/multicast.cc | 21 +++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index 7aec1accb30..de9ccb086e5 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -710,6 +710,17 @@ bool AgentRoute::ReComputeMulticastPaths(AgentPath *path, bool del) { return false; } + //HACK: subnet route uses multicast NH. During IPAM delete + //subnet discard is deleted. Consider this as delete of all + //paths. Though this can be handled via multicast module + //which can also issue delete of all peers, however + //this is a temporary code as subnet route will not use + //multicast NH. + bool delete_all = false; + if (path->is_subnet_discard() && del) { + delete_all = true; + } + Agent *agent = (static_cast (get_table()))->agent(); std::vector delete_paths; @@ -735,6 +746,10 @@ bool AgentRoute::ReComputeMulticastPaths(AgentPath *path, bool del) { it != GetPathList().end(); it++) { AgentPath *it_path = static_cast(it.operator->()); + + if (delete_all && (it_path->peer() != agent->multicast_peer())) + continue; + //Handle deletions if (del && (path->peer() == it_path->peer())) { continue; diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index 5db7933075d..d4496fd32c7 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -36,6 +36,18 @@ using AGENT::PhysicalDeviceEntry; MulticastHandler *MulticastHandler::obj_; SandeshTraceBufferPtr MulticastTraceBuf(SandeshTraceBufferCreate("Multicast", 1000)); + +Composite::Type GetCompositeTypeFromPeer(const Peer *peer) { + if (peer->GetType() == Peer::MULTICAST_TOR_PEER) + return Composite::TOR; + else if (peer->GetType() == Peer::BGP_PEER) + return Composite::EVPN; + else if (peer->GetType() == Peer::MULTICAST_FABRIC_TREE_BUILDER) + return Composite::FABRIC; + else + return Composite::L2INTERFACE; +} + /* * Registeration for notification * VM - Looking for local VM added @@ -101,6 +113,11 @@ void MulticastHandler::DeleteBroadcast(const Peer *peer, boost::system::error_code ec; MCTRACE(Log, "delete bcast route ", vrf_name, "255.255.255.255", 0); Layer2AgentRouteTable::DeleteBroadcastReq(peer, vrf_name, ethernet_tag); + ComponentNHKeyList component_nh_key_list; //dummy list + RebakeSubnetRoute(Agent::GetInstance()->multicast_tor_peer(), + vrf_name, 0, ethernet_tag, "", + true, component_nh_key_list, + GetCompositeTypeFromPeer(peer)); } void MulticastHandler::HandleVxLanChange(const VnEntry *vn) { @@ -760,10 +777,6 @@ void MulticastHandler::RebakeSubnetRoute(const Peer *peer, const ComponentNHKeyList &comp_nh_list, COMPOSITETYPE comp_type) { - if (peer->GetType() != Peer::MULTICAST_TOR_PEER && - peer->GetType() != Peer::BGP_PEER) { - return; - } std::vector &vrf_ipam = (vrf_ipam_mapping_.find(vrf_name))->second; for (std::vector::iterator it = vrf_ipam.begin();