Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions agent-ovs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ libopflex_agent_la_include_HEADERS = \
lib/include/opflexagent/Fault.h \
lib/include/opflexagent/Agent.h \
lib/include/opflexagent/IdGenerator.h \
lib/include/opflexagent/interface_utils.h \
lib/include/opflexagent/KeyedRateLimiter.h \
lib/include/opflexagent/MulticastListener.h \
lib/include/opflexagent/TaskQueue.h \
Expand Down Expand Up @@ -222,6 +223,7 @@ libopflex_agent_la_SOURCES = \
lib/Fault.cpp \
lib/Agent.cpp \
lib/IdGenerator.cpp \
lib/interface_utils.cpp \
lib/NotifServer.cpp \
lib/MulticastListener.cpp \
lib/TaskQueue.cpp \
Expand Down
64 changes: 1 addition & 63 deletions agent-ovs/lib/TunnelEpManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <opflexagent/TunnelEpManager.h>
#include <opflexagent/Renderer.h>
#include <opflexagent/logging.h>
#include <opflexagent/interface_utils.h>

namespace opflexagent {

Expand Down Expand Up @@ -106,69 +107,6 @@ const std::string& TunnelEpManager::getTerminationMac(const std::string& uuid) {
return terminationMac;
}

#ifdef HAVE_IFADDRS_H
static string getInterfaceMac(const string& iface) {
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
int err = errno;
LOG(ERROR) << "Socket creation failed when getting MAC address of "
<< iface << ", error: " << strerror(err);
return "";
}

ifreq ifReq;
/* Note: ifReq.ifr_name is 16 bytes. Ensure at most we can copy only 15 bytes.
* 1 byte must be reserved for null terminating the string */
auto maxSize = strnlen(iface.c_str(), sizeof(ifReq.ifr_name)-1);
strncpy(ifReq.ifr_name, iface.c_str(), maxSize);
ifReq.ifr_name[maxSize] = '\0';
if (ioctl(sock, SIOCGIFHWADDR, &ifReq) != -1) {
close(sock);
return
opflex::modb::MAC((uint8_t*)(ifReq.ifr_hwaddr.sa_data)).toString();
} else {
int err = errno;
close(sock);
LOG(ERROR) << "ioctl to get MAC address failed for " << iface
<< ", error: " << strerror(err);
return "";
}
}

static string getInterfaceAddressV4(const string& iface) {
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
int err = errno;
LOG(ERROR) << "Socket creation failed when getting IPv4 address of "
<< iface << ", error: " << strerror(err);
return "";
}

ifreq ifReq;
/* Note: ifReq.ifr_name is 16 bytes. Ensure at most we can copy only 15 bytes.
* 1 byte must be reserved for null terminating the string */
auto maxSize = strnlen(iface.c_str(), sizeof(ifReq.ifr_name)-1);
strncpy(ifReq.ifr_name, iface.c_str(), maxSize);
ifReq.ifr_name[maxSize] = '\0';
if (ioctl(sock, SIOCGIFADDR, &ifReq) != -1) {
close(sock);
char host[NI_MAXHOST];
int s = getnameinfo(&ifReq.ifr_addr, sizeof(struct sockaddr_in),
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(s);
return "";
}
return host;
} else {
int err = errno;
close(sock);
LOG(ERROR) << "ioctl to get IPv4 address failed for " << iface
<< ", error: " << strerror(err);
return "";
}
}
#endif

void TunnelEpManager::on_timer(const error_code& ec) {
if (ec) {
Expand Down
38 changes: 38 additions & 0 deletions agent-ovs/lib/include/opflexagent/interface_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* -*- C++ -*-; c-basic-offset: 4; indent-tabs-mode: nil */
/*
* Interface utility functions for querying network interface properties
*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/

#include <string>

#pragma once
#ifndef OPFLEXAGENT_INTERFACE_UTILS_H
#define OPFLEXAGENT_INTERFACE_UTILS_H

namespace opflexagent {

/**
* Get the MAC address for a given interface name
*
* @param iface the interface name
* @return the MAC address as a string, or empty string on error
*/
std::string getInterfaceMac(const std::string& iface);

/**
* Get the IPv4 address for a given interface name
*
* @param iface the interface name
* @return the IPv4 address as a string, or empty string on error
*/
std::string getInterfaceAddressV4(const std::string& iface);

} /* namespace opflexagent */

#endif /* OPFLEXAGENT_INTERFACE_UTILS_H */
108 changes: 108 additions & 0 deletions agent-ovs/lib/interface_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* -*- C++ -*-; c-basic-offset: 4; indent-tabs-mode: nil */
/*
* Implementation of interface utility functions
*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_IFADDRS_H
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netdb.h>
#include <unistd.h>
#endif
#include <cerrno>
#include <cstring>

#include <opflex/modb/MAC.h>
#include <opflexagent/interface_utils.h>
#include <opflexagent/logging.h>

namespace opflexagent {

using std::string;

#ifdef HAVE_IFADDRS_H
string getInterfaceMac(const string& iface) {
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
int err = errno;
LOG(ERROR) << "Socket creation failed when getting MAC address of "
<< iface << ", error: " << strerror(err);
return "";
}

ifreq ifReq;
/* Note: ifReq.ifr_name is 16 bytes. Ensure at most we can copy only 15 bytes.
* 1 byte must be reserved for null terminating the string */
auto maxSize = strnlen(iface.c_str(), sizeof(ifReq.ifr_name)-1);
strncpy(ifReq.ifr_name, iface.c_str(), maxSize);
ifReq.ifr_name[maxSize] = '\0';
if (ioctl(sock, SIOCGIFHWADDR, &ifReq) != -1) {
close(sock);
return
opflex::modb::MAC((uint8_t*)(ifReq.ifr_hwaddr.sa_data)).toString();
} else {
int err = errno;
close(sock);
LOG(ERROR) << "ioctl to get MAC address failed for " << iface
<< ", error: " << strerror(err);
return "";
}
}

string getInterfaceAddressV4(const string& iface) {
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
int err = errno;
LOG(ERROR) << "Socket creation failed when getting IPv4 address of "
<< iface << ", error: " << strerror(err);
return "";
}

ifreq ifReq;
/* Note: ifReq.ifr_name is 16 bytes. Ensure at most we can copy only 15 bytes.
* 1 byte must be reserved for null terminating the string */
auto maxSize = strnlen(iface.c_str(), sizeof(ifReq.ifr_name)-1);
strncpy(ifReq.ifr_name, iface.c_str(), maxSize);
ifReq.ifr_name[maxSize] = '\0';
if (ioctl(sock, SIOCGIFADDR, &ifReq) != -1) {
close(sock);
char host[NI_MAXHOST];
int s = getnameinfo(&ifReq.ifr_addr, sizeof(struct sockaddr_in),
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(s);
return "";
}
return host;
} else {
int err = errno;
close(sock);
LOG(ERROR) << "ioctl to get IPv4 address failed for " << iface
<< ", error: " << strerror(err);
return "";
}
}
#else
string getInterfaceMac(const string& iface) {
LOG(ERROR) << "Cannot get interface MAC address: unsupported platform";
return "";
}

string getInterfaceAddressV4(const string& iface) {
LOG(ERROR) << "Cannot get interface IPv4 address: unsupported platform";
return "";
}
#endif

} /* namespace opflexagent */
9 changes: 9 additions & 0 deletions agent-ovs/ovs/OVSRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "OVSRenderer.h"
#include <opflexagent/logging.h>
#include <opflexagent/interface_utils.h>
#include <sstream>
#include <boost/asio/placeholders.hpp>
#include <openvswitch/vlog.h>
Expand Down Expand Up @@ -120,6 +121,14 @@ void OVSRenderer::start() {
tunnelEpManager.setParentRenderer(this);
tunnelEpManager.start();
}
else if (encapType == IntFlowManager::ENCAP_VLAN) {
if (!uplinkIface.empty()) {
std::string uplinkMac = getInterfaceMac(uplinkIface);
if (!uplinkMac.empty()) {
getAgent().setUplinkMac(uplinkMac);
}
}
}

if (!flowIdCache.empty())
idGen.setPersistLocation(flowIdCache);
Expand Down
Loading