Daynaport device can be configured with interface list (issue #202)

This commit is contained in:
Uwe Seimet 2021-08-24 20:05:16 +02:00
parent e336e726cb
commit 106d2d50d1
10 changed files with 92 additions and 70 deletions

View File

@ -26,7 +26,7 @@
#include "ctapdriver.h"
#include "log.h"
#include "exceptions.h"
#include <string>
#include <sstream>
using namespace std;
@ -35,9 +35,14 @@ using namespace std;
// Constructor
//
//---------------------------------------------------------------------------
CTapDriver::CTapDriver()
CTapDriver::CTapDriver(const string& interfaces)
{
LOGTRACE("%s",__PRETTY_FUNCTION__);
stringstream s(interfaces);
string interface;
while (getline(s, interface, ',')) {
this->interfaces.push_back(interface);
}
// Initialization
m_bTxValid = FALSE;
m_hTAP = -1;
@ -88,7 +93,7 @@ static BOOL ip_link(int fd, const char* ifname, BOOL up) {
return TRUE;
}
static bool is_interface_up(const char *interface) {
static bool is_interface_up(const string& interface) {
string file = "/sys/class/net/";
file += interface;
file += "/carrier";
@ -150,24 +155,31 @@ BOOL CTapDriver::Init()
return FALSE;
}
// Check if the bridge is already created
// Check if the bridge has already been created
if (access("/sys/class/net/rascsi_bridge", F_OK) != 0) {
LOGINFO("rascsi_bridge is not yet available");
LOGINFO("Checking whether to create bridge for interface eth0 or wlan0");
const char *interface = NULL;
if (is_interface_up("eth0")) {
interface = "eth0";
LOGTRACE("Checking which interface is available for creating the bridge");
string interface;
for (auto it = interfaces.begin(); it != interfaces.end(); ++it) {
if (is_interface_up(*it)) {
LOGTRACE(string("Interface " + (*it) + " is up").c_str());
interface = *it;
break;
}
else {
LOGTRACE(string("Interface " + (*it) + " is not up").c_str());
}
}
else if (is_interface_up("wlan0")) {
interface = "wlan0";
}
if (!interface) {
LOGERROR("Neither interface eth0 nor wlan0 is up, not creating bridge");
if (interface.empty()) {
LOGERROR("No interface is up, not creating bridge");
return FALSE;
}
LOGINFO("Creating rascsi_bridge for interface %s...", interface);
LOGINFO("Creating rascsi_bridge for interface %s", interface.c_str());
LOGDEBUG("brctl addbr rascsi_bridge");
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) {
LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno));
@ -176,16 +188,17 @@ BOOL CTapDriver::Init()
close(br_socket_fd);
return FALSE;
}
if (strcmp(interface, "wlan0")) {
LOGDEBUG("brctl addif rascsi_bridge %s", interface);
if (!br_setif(br_socket_fd, "rascsi_bridge", interface, TRUE)) {
if (interface == "eth0") {
LOGDEBUG("brctl addif rascsi_bridge %s", interface.c_str());
if (!br_setif(br_socket_fd, "rascsi_bridge", interface.c_str(), TRUE)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
}
if (!strcmp(interface, "wlan0")) {
else {
LOGDEBUG("ip address add 10.10.20.1/24 dev rascsi_bridge");
struct ifreq ifr_a;
ifr_a.ifr_addr.sa_family = AF_INET;

View File

@ -18,6 +18,8 @@
#include <pcap/pcap.h>
#include "filepath.h"
#include <vector>
#include <string>
#ifndef ETH_FRAME_LEN
#define ETH_FRAME_LEN 1514
@ -32,8 +34,8 @@ class CTapDriver
{
public:
// Basic Functionality
CTapDriver(); // Constructor
BOOL Init(); // Initilization
CTapDriver(const std::string&); // Constructor
BOOL Init(); // Initialization
void OpenDump(const Filepath& path);
// Capture packets
void Cleanup(); // Cleanup
@ -55,6 +57,8 @@ private:
pcap_t *m_pcap;
pcap_dumper_t *m_pcap_dumper;
// Prioritized comma-separated list of interfaces to create the bridge for
std::vector<std::string> interfaces;
};
#endif // ctapdriver_h

View File

@ -92,7 +92,7 @@ public:
virtual ~Device() {};
// Override for device specific initializations, to be called after all device properties have been set
virtual void Init() {};
virtual void Init(const string&) {};
virtual bool Dispatch(SCSIDEV *) = 0;

View File

@ -77,11 +77,11 @@ SCSIDaynaPort::~SCSIDaynaPort()
}
}
void SCSIDaynaPort::Init()
void SCSIDaynaPort::Init(const string& interfaces)
{
#ifdef __linux__
// TAP Driver Generation
m_tap = new CTapDriver();
m_tap = new CTapDriver(!interfaces.empty() ? interfaces : "eth0,wlan0");
m_bTapEnable = m_tap->Init();
if(!m_bTapEnable){
LOGERROR("Unable to open the TAP interface");
@ -115,8 +115,6 @@ void SCSIDaynaPort::Init()
void SCSIDaynaPort::Open(const Filepath& path)
{
LOGTRACE("SCSIDaynaPort Open");
m_tap->OpenDump(path);
}

View File

@ -33,6 +33,7 @@
#include "disk.h"
#include "ctapdriver.h"
#include <map>
#include <string>
//===========================================================================
//
@ -60,7 +61,7 @@ public:
SCSIDaynaPort();
~SCSIDaynaPort();
void Init() override;
void Init(const string&) override;
void Open(const Filepath& path);
// Capture packets

View File

@ -21,6 +21,8 @@
#include "ctapdriver.h"
#include "cfilesystem.h"
using namespace std;
//===========================================================================
//
// SCSI Host Bridge
@ -76,11 +78,11 @@ SCSIBR::~SCSIBR()
}
}
void SCSIBR::Init()
void SCSIBR::Init(const string&)
{
#ifdef __linux__
// TAP Driver Generation
tap = new CTapDriver();
tap = new CTapDriver("");
m_bTapEnable = tap->Init();
// Generate MAC Address

View File

@ -20,6 +20,7 @@
#include "xm6.h"
#include "os.h"
#include "disk.h"
#include <string>
//===========================================================================
//
@ -49,7 +50,7 @@ public:
SCSIBR();
~SCSIBR();
void Init() override;
void Init(const string&) override;
bool Dispatch(SCSIDEV *) override;

View File

@ -592,14 +592,13 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
const int id = pbDevice.id();
const int unit = pbDevice.unit();
const string filename = pbDevice.file();
PbDeviceType type = pbDevice.type();
bool all = params == "all";
ostringstream s;
s << (dryRun ? "Validating: " : "Executing: ");
s << "cmd=" << PbOperation_Name(cmd) << ", id=" << id << ", unit=" << unit << ", type=" << PbDeviceType_Name(type)
<< ", filename='" << filename << "', vendor='" << pbDevice.vendor()
<< ", params='" << pbDevice.params() << "', vendor='" << pbDevice.vendor()
<< ", product='" << pbDevice.product() << "', revision='" << pbDevice.revision() << "'"
<< "', block size=" << pbDevice.block_size() << ", params='" << params << "'";
LOGINFO("%s", s.str().c_str());
@ -628,6 +627,7 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
return ReturnStatus(fd, false, error);
}
string filename = pbDevice.params();
string ext;
int len = filename.length();
if (len > 4 && filename[len - 4] == '.') {
@ -736,7 +736,7 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
}
// Initialize everything that would have caused issues when being initialized during the dry run
device->Init();
device->Init(pbDevice.params());
// Replace with the newly created unit
map[id * UnitNum + unit] = device;
@ -819,39 +819,42 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
}
switch (cmd) {
case INSERT:
if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) {
return ReturnStatus(fd, false, "Device name cannot be changed");
}
if (filename.empty()) {
return ReturnStatus(fd, false, "Missing filename");
}
if (dryRun) {
return true;
}
filepath.SetPath(filename.c_str());
LOGINFO("Insert file '%s' requested into %s ID: %d unit: %d", filename.c_str(), device->GetType().c_str(), id, unit);
try {
fileSupport->Open(filepath);
}
catch(const io_exception& e) {
if (!default_image_folder.empty()) {
// If the file does not exist search for it in the default image folder
string default_file = default_image_folder + "/" + filename;
filepath.SetPath(default_file.c_str());
try {
fileSupport->Open(filepath);
}
catch(const io_exception&) {
return ReturnStatus(fd, false, "Tried to open an invalid file '" + filename + "': " + e.getmsg());
}
case INSERT: {
if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) {
return ReturnStatus(fd, false, "Device name cannot be changed");
}
else {
return ReturnStatus(fd, false, "No default image folder");
string filename = pbDevice.params();
if (filename.empty()) {
return ReturnStatus(fd, false, "Missing filename");
}
if (dryRun) {
return true;
}
filepath.SetPath(filename.c_str());
LOGINFO("Insert file '%s' requested into %s ID: %d unit: %d", filename.c_str(), device->GetType().c_str(), id, unit);
try {
fileSupport->Open(filepath);
}
catch(const io_exception& e) {
if (!default_image_folder.empty()) {
// If the file does not exist search for it in the default image folder
string default_file = default_image_folder + "/" + filename;
filepath.SetPath(default_file.c_str());
try {
fileSupport->Open(filepath);
}
catch(const io_exception&) {
return ReturnStatus(fd, false, "Tried to open an invalid file '" + filename + "': " + e.getmsg());
}
}
else {
return ReturnStatus(fd, false, "No default image folder");
}
}
}
break;
@ -1030,7 +1033,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
device->set_unit(unit);
device->set_type(type);
device->set_block_size(block_size);
device->set_file(optarg);
device->set_params(optarg);
size_t separatorPos = name.find(':');
if (separatorPos != string::npos) {

View File

@ -61,10 +61,10 @@ message PbDeviceDefinition {
int32 id = 1;
int32 unit = 2;
PbDeviceType type = 3;
// Optional device specific parameter, e.g. the name of an image file
string params = 4;
// The optional SCSI hard disk drive block size in bytes per sector, must be 512, 1024, 2048 or 4096
int32 block_size = 4;
// The optional name of the image file
string file = 5;
int32 block_size = 5;
// The device name components
string vendor = 6;
string product = 7;

View File

@ -360,7 +360,7 @@ int main(int argc, char* argv[])
break;
case 'f':
device->set_file(optarg);
device->set_params(optarg);
break;
case 't':