diff --git a/click/conf/xia_router_lib.click b/click/conf/xia_router_lib.click index 8b56e1de0..23ec57372 100644 --- a/click/conf/xia_router_lib.click +++ b/click/conf/xia_router_lib.click @@ -362,6 +362,27 @@ elementclass XIARoutingCore { // For get and put cid } +elementclass XIAOverlayRouter { + of0::XIAOverlayFilter(); + of1::XIAOverlayFilter(); + of2::XIAOverlayFilter(); + of3::XIAOverlayFilter(); + + rd::XIAOverlayRouted(); + + input -> rd; + rd[0] -> of0 -> [0]output; + rd[1] -> of1 -> [1]output; + rd[2] -> of2 -> [2]output; + rd[3] -> of3 -> [3]output; + + // discard remaining of ports + of0[1]->[1]of0; of0[2]->Discard; of0[3]->Discard; + of1[1]->[1]of1; of1[2]->Discard; of1[3]->Discard; + of2[1]->[1]of2; of2[2]->Discard; of2[3]->Discard; + of3[1]->[1]of3; of3[2]->Discard; of3[3]->Discard; +} + // 2-port router elementclass XIARouter2Port { $click_port, $hostname, $external_ip, $mac0, $mac1, | @@ -384,6 +405,7 @@ elementclass XIARouter2Port { }; // 4-port router node + elementclass XIARouter4Port { $click_port, $hostname, $external_ip, $mac0, $mac1, $mac2, $mac3 | diff --git a/click/elements/xia/xiaoverlayrouted.cc b/click/elements/xia/xiaoverlayrouted.cc new file mode 100644 index 000000000..e5c7e1e86 --- /dev/null +++ b/click/elements/xia/xiaoverlayrouted.cc @@ -0,0 +1,604 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "click/dagaddr.hpp" +#include "xiaoverlayrouted.hh" +#include +#include +#include +#include + + +#define XID_SIZE CLICK_XIA_XID_ID_LEN + +#define SID_XOVERLAY "SID:1110000000000000000000000000000000001111" + +CLICK_DECLS + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INCLUDE_TEST_CODE 0 + + +#define check_init() do { if (!_init) return init_err; } while (false); + + +void +XIAOverlayRouted::add_handlers() +{ + add_write_handler("neighbor", add_neighbor, 0); +} + +int +XIAOverlayRouted::add_neighbor(const String &conf, Element *e, void *thunk, ErrorHandler *errh) +{ + printf("Called add neighbor\n"); + XIAOverlayRouted *r = static_cast(e); + + Vector args; + cp_argvec(conf, args); + + if (args.size() != 4) + return errh->error("Invalid args: ", conf.c_str()); + + int port = 0; + String addr, sid, ad, hid; + + if (!cp_string(args[0], &addr)) + return errh->error("Invalid addr"); + + if (!cp_string(args[1], &ad)) + return errh->error("Invalid AD"); + + // if (!cp_string(args[2], &hid)) + // return errh->error("Invalid HID"); + + if (!cp_string(args[2], &sid)) + return errh->error("Invalid SID"); + + if (!cp_integer(args[3], &port)) + return errh->error("Invalid port"); + + + printf("Adding NeighborEntry addr:%s AD:%s SID:%s port:%d\n", + addr.c_str(), ad.c_str(), sid.c_str(), port); + + NeighborEntry *entry = new NeighborEntry(); + entry->addr.append(addr.c_str()); + entry->AD.append(ad.c_str()); + entry->SID.append(sid.c_str()); + entry->port = port; + + //todo: check if the entry already exits + r->route_state.neighborTable[entry->AD] = entry; + + return 0; +} + + +XIAOverlayRouted::XIAOverlayRouted() +{ + + FILE *f = fopen("etc/address.conf", "r"); + if (!f) { + printf("Failed to open resolv.conf \n"); + return; + } + char *hostname = (char *)malloc(32); + assert(hostname); + char ad[100], hid[100], re[100]; + fscanf(f,"%s %s %s %s", hostname, re, ad, hid); + fclose(f); + + strcpy(route_state.myAD, ad+1); + strncpy(route_state.myHID, hid, XID_SIZE); + + route_state.num_neighbors = 0; // number of neighbor routers + route_state.calc_dijstra_ticks = 0; + + route_state.flags = F_EDGE_ROUTER; + + route_state.dual_router_AD = "NULL"; + _hostname = String(hostname, strlen(hostname)); + printf("\n----XIAOverlayRouted: Started with ad: %s hid: %s hostname: %s----\n", route_state.myAD, + route_state.myHID, _hostname.c_str()); + c = 0; +} + +XIAOverlayRouted::~XIAOverlayRouted() +{ +} + +std::string +XIAOverlayRouted::sendLSA() { + string message; + + Node n_ad(route_state.myAD); + printf("XIAOverlayRouted: sending lsa with ad %s\n", n_ad.to_string().c_str()); + // Node n_hid(route_state.myHID); + + Xroute::XrouteMsg msg; + Xroute::LSAMsg *lsa = msg.mutable_lsa(); + Xroute::Node *node = lsa->mutable_node(); + Xroute::XID *ad = node->mutable_ad(); + // Xroute::XID *hid = node->mutable_hid(); + + msg.set_type(Xroute::LSA_MSG); + msg.set_version(Xroute::XROUTE_PROTO_VERSION); + + lsa->set_flags(route_state.flags); + ad ->set_type(n_ad.type()); + ad ->set_id(n_ad.id(), XID_SIZE); + // hid->set_type(n_hid.type()); + // hid->set_id(n_hid.id(), XID_SIZE); + + map::iterator it; + for ( it=route_state.neighborTable.begin() ; it != route_state.neighborTable.end(); it++ ) { + Node p_ad(it->second->AD); + // Node p_hid(it->second.HID); + + node = lsa->add_peers(); + ad = node->mutable_ad(); + // hid = node->mutable_hid(); + + ad ->set_type(p_ad.type()); + ad ->set_id(p_ad.id(), XID_SIZE); + // hid->set_type(p_hid.type()); + // hid->set_id(p_hid.id(), XID_SIZE); + } + + msg.SerializeToString(&message); + + return message; +} + +std::string +XIAOverlayRouted::sendHello() +{ + int buflen, rc; + string message; + Node n_ad(route_state.myAD); + Node n_hid(route_state.myHID); + Node n_sid(SID_XOVERLAY); + + Xroute::XrouteMsg msg; + Xroute::HelloMsg *hello = msg.mutable_hello(); + Xroute::Node *node = hello->mutable_node(); + Xroute::XID *ad = node->mutable_ad(); + Xroute::XID *hid = node->mutable_hid(); + Xroute::XID *sid = node->mutable_sid(); + + msg.set_type(Xroute::HELLO_MSG); + msg.set_version(Xroute::XROUTE_PROTO_VERSION); + hello->set_flags(route_state.flags); + ad->set_type(n_ad.type()); + ad->set_id(n_ad.id(), XID_SIZE); + hid->set_type(n_hid.type()); + hid->set_id(n_hid.id(), XID_SIZE); + sid->set_type(n_sid.type()); + sid->set_id(n_sid.id(), XID_SIZE); + + msg.SerializeToString(&message); + return message; +} + +int +XIAOverlayRouted::processLSA(const Xroute::XrouteMsg &msg) { + + string neighborAD, neighborHID, myAD; + string destAD, destHID; + + // fix me once we don't need to rebroadcast the lsa + const Xroute::LSAMsg& lsa = msg.lsa(); + + Xroute::XID a = lsa.node().ad(); + + Node ad(a.type(), a.id().c_str(), 0); + + destAD = ad.to_string(); + printf("\n\nIn processLSA with destAD %s\n", destAD.c_str()); + // FIXME: this only allows for a single dual stack router in the network + if (lsa.flags() & F_IP_GATEWAY) { + route_state.dual_router_AD = destAD; + } + + if (destAD.compare(route_state.myAD) == 0) { + // skip if from me + return 1; + } + + printf("In processLSA\n"); + + map::iterator it = route_state.networkTable.find(destAD); + if(it != route_state.networkTable.end()) { + // For now, delete this dest AD entry in networkTable + // (... we will re-insert the updated entry shortly) + route_state.networkTable.erase (it); + } + + // don't bother if there's nothing there??? + if (lsa.peers_size() == 0) { + return 1; + } + + + // 2. Update the network table + NodeStateEntry entry; + entry.dest = destAD; + entry.num_neighbors = lsa.peers_size(); + + for (int i = 0; i < lsa.peers_size(); i++) { + + Node a(lsa.peers(i).ad().type(), lsa.peers(i).ad().id().c_str(), 0); +// Node h(lsa.peers(i).hid().type(), lsa.peers(i).hid().id().c_str(), 0); + + neighborAD = a.to_string(); +// neighborHID = h.to_string(); + + // fill the neighbors into the corresponding networkTable entry + entry.neighbor_list.push_back(neighborAD); + printf("Adding neighbor entry %s\n", neighborAD.c_str()); + } + + route_state.networkTable[destAD] = entry; + + + printf("LSA received src=%s, num_neighbors=%d \n", + (route_state.networkTable[destAD].dest).c_str(), + route_state.networkTable[destAD].num_neighbors ); + + + // route_state.calc_dijstra_ticks++; + + // if (route_state.calc_dijstra_ticks == CALC_DIJKSTRA_INTERVAL) { + // // Calculate Shortest Path algorithm + printf("Calcuating shortest paths\n"); + calcShortestPath(); + route_state.calc_dijstra_ticks = 0; + + // update Routing table (click routing table as well) + updateClickRoutingTable(); + // } + + return 1; +} + +void +XIAOverlayRouted::calcShortestPath() { + + // first, clear the current routing table + route_state.ADrouteTable.clear(); + + map::iterator it1; + for ( it1=route_state.networkTable.begin() ; it1 != route_state.networkTable.end();) { + + // filter out an abnormal case + if(it1->second.num_neighbors == 0 || (it1->second.dest).empty() ) { + route_state.networkTable.erase (it1++); + } else { + ++it1; + } + } + + + // work on a copy of the table + map table; + table = route_state.networkTable; + + for ( it1=route_state.networkTable.begin() ; it1 != route_state.networkTable.end(); it1++ ) { + // initialize the checking variable + it1->second.checked = false; + it1->second.cost = 10000000; + } + + // compute shortest path + // initialization + string myAD, tempAD; + myAD = route_state.myAD; + route_state.networkTable[myAD].checked = true; + route_state.networkTable[myAD].cost = 0; + table.erase(myAD); + + vector::iterator it2; + for ( it2=route_state.networkTable[myAD].neighbor_list.begin() ; it2 < route_state.networkTable[myAD].neighbor_list.end(); it2++ ) { + + tempAD = (*it2).c_str(); + route_state.networkTable[tempAD].cost = 1; + route_state.networkTable[tempAD].prevNode = myAD; + } + + // loop + while (!table.empty()) { + int minCost = 10000000; + string selectedAD, tmpAD; + for ( it1=table.begin() ; it1 != table.end(); it1++ ) { + tmpAD = it1->second.dest; + if (route_state.networkTable[tmpAD].cost < minCost) { + minCost = route_state.networkTable[tmpAD].cost; + selectedAD = tmpAD; + } + } + if(selectedAD.empty()) { + return; + } + + table.erase(selectedAD); + route_state.networkTable[selectedAD].checked = true; + + for ( it2=route_state.networkTable[selectedAD].neighbor_list.begin() ; it2 < route_state.networkTable[selectedAD].neighbor_list.end(); it2++ ) { + tempAD = (*it2).c_str(); + if (route_state.networkTable[tempAD].checked != true) { + if (route_state.networkTable[tempAD].cost > route_state.networkTable[selectedAD].cost + 1) { + route_state.networkTable[tempAD].cost = route_state.networkTable[selectedAD].cost + 1; + route_state.networkTable[tempAD].prevNode = selectedAD; + } + } + } + } + + string tempAD1, tempAD2; + int hop_count; + // set up the nexthop + for ( it1=route_state.networkTable.begin() ; it1 != route_state.networkTable.end(); it1++ ) { + + tempAD1 = it1->second.dest; + if ( myAD.compare(tempAD1) != 0 ) { + tempAD2 = tempAD1; + hop_count = 0; + while (route_state.networkTable[tempAD2].prevNode.compare(myAD)!=0 && hop_count < MAX_HOP_COUNT) { + tempAD2 = route_state.networkTable[tempAD2].prevNode; + hop_count++; + } + if(hop_count < MAX_HOP_COUNT) { + route_state.ADrouteTable[tempAD1].dest = tempAD1; + // route_state.ADrouteTable[tempAD1].nextHop = route_state.neighborTable[tempAD2].HID; + route_state.ADrouteTable[tempAD1].nextHop = route_state.neighborTable[tempAD2]->AD; + route_state.ADrouteTable[tempAD1].port = route_state.neighborTable[tempAD2]->port; + } + } + } + printRoutingTable(); +} + +void +XIAOverlayRouted::printRoutingTable() { + + printf("AD Routing table at %s", route_state.myAD); + map::iterator it1; + for ( it1=route_state.ADrouteTable.begin() ; it1 != route_state.ADrouteTable.end(); it1++ ) { + printf("Dest=%s, NextHop=%s, Port=%d, Flags=%u", (it1->second.dest).c_str(), + (it1->second.nextHop).c_str(), (it1->second.port), (it1->second.flags) ); + } +} + + +void +XIAOverlayRouted::updateClickRoutingTable() { + + int rc, port; + uint32_t flags; + string destXID, nexthopXID; + string default_AD("AD:-"), default_HID("HID:-"), default_4ID("IP:-"); + + map::iterator it1; + for ( it1=route_state.ADrouteTable.begin() ; it1 != route_state.ADrouteTable.end(); it1++ ) { + destXID = it1->second.dest; + nexthopXID = it1->second.nextHop; + port = it1->second.port; + flags = it1->second.flags; + + if ((rc = updateRoute("set4", destXID, port, nexthopXID, flags)) != 0) + printf("error setting route %d", rc); + + // set default AD for 4ID traffic + if (!(route_state.flags & F_IP_GATEWAY) && destXID.compare(route_state.dual_router_AD) == 0) { + if ((rc = updateRoute("set4", default_4ID, port, nexthopXID, flags)) != 0) + printf("error setting route %d", rc); + } + } + // listRoutes("AD"); + // listRoutes("HID"); +} + +String XIAOverlayRouted::itoa(signed i) +{ + std::string s; + std::stringstream ss; + + ss << i; + s = ss.str(); + return String(s.c_str()); +} + +int +XIAOverlayRouted::updateRoute(string cmd, const std::string &xid, int port, + const std::string &next, unsigned long flags) +{ + string xidtype; + string mutableXID(xid); + size_t n; + + if (mutableXID.length() == 0) + return 1; + + if (next.length() > 0 && next.find(":") == string::npos) + return 1; + + n = mutableXID.find(":"); + if (n == string::npos || n >= sizeof(xidtype)) + return 1; + + xidtype = mutableXID.substr(0, n); + + + std::string table = std::string(_hostname.c_str()) + "/xrc/n/proc/rt_" + xidtype; + + string default_xid("-"); + if (mutableXID.compare(n+1, 1, default_xid) == 0) + mutableXID = default_xid; + + String entry; + + // remove command only takes an xid + if (cmd == "remove") + entry = mutableXID.c_str(); + else { + String sep(","); + entry = String(mutableXID.c_str()) + sep + itoa(port) + sep + String(next.c_str()) + sep + itoa(flags); + } + + printf("\nXIAOverlayRouted: updateRoute for %s \n",entry.c_str()); + + Element *re = this->router()->find(String(table.c_str())); + if(re) { + int ret = HandlerCall::call_write(re, cmd.c_str(), entry); + if(ret) + { + printf("HandlerCall failed\n"); + return 2; + } + } + else { + printf("Element not found"); + return 2; + } + + return 0; +} + +void +XIAOverlayRouted::neighbor_broadcast(std::string msg) { + std::map::iterator it; + for(it=route_state.neighborTable.begin(); it != route_state.neighborTable.end(); it++) { + String dst(it->second->addr.c_str()); + int port = it->second->port; + _push_msg(msg, dst, port); + } +} + +void +XIAOverlayRouted::_push_msg(std::string msg, String dst, int port) { + + struct click_ip *ip; + struct click_udp *udp; + + size_t qsize = sizeof(*ip) + sizeof(*udp) + msg.length(); + + WritablePacket *q = Packet::make(qsize); + memset(q->data(), '0', q->length()); + ip = (struct click_ip *) q->data(); + udp = (struct click_udp *) (ip + 1); + char *data = (char *)(udp+1); + memcpy(data, msg.c_str(), msg.length()); + + ip->ip_v = 4; + ip->ip_hl = 5; + ip->ip_tos = 0x10; + ip->ip_len = htons(q->length()); + ip->ip_id = htons(0); // what is this used for exactly? + ip->ip_off = htons(IP_DF); + ip->ip_ttl = 255; + ip->ip_p = IP_PROTO_UDP; + ip->ip_sum = 0; + + //todo: fill source address + // struct in_addr *saddr = (struct in_addr *)malloc(sizeof(struct in_addr)); + struct in_addr *daddr = (struct in_addr *)malloc(sizeof(struct in_addr)); + // assert(saddr); + assert(daddr); + // inet_aton("10.0.1.128", saddr); + // ip->ip_src = *saddr; + + //todo: make this configurable + udp->uh_sport = htons(8772); + udp->uh_dport = htons(8772); + udp->uh_ulen = htons(msg.length()); + + q->set_ip_header(ip, ip->ip_hl << 2); + + + inet_aton(dst.c_str(), daddr); + ip->ip_dst = *daddr; + q->set_dst_ip_anno(IPAddress(*daddr)); + SET_DST_PORT_ANNO(q, htons(8772)); + // int port = it->second->port; + printf("XIAOverlayRouted: Pushing packet len %d to %s, port :%d\n", + q->length(), inet_ntoa(*daddr), port); + output(port).push(q); + +} + +void +XIAOverlayRouted::push(int port, Packet *p_in) +{ + struct click_ip *ip; + struct click_udp *udp; + + size_t a = sizeof(*ip) + sizeof(*udp); + printf("XIAOverlayRouted: received packet of %d\n", p_in->length()); + Xroute::XrouteMsg xmsg; + if(p_in->length() > a) { + + ip = (struct click_ip *) p_in->data(); + udp = (struct click_udp *) (ip + 1); + size_t mlen = p_in->length()-a; + string cs(((const char *)(udp + 1)), mlen); + if(!xmsg.ParseFromString(cs)) { + printf("XIAOverlayRouted : could not understand packet\n"); + } + else { + if(xmsg.type() == Xroute::HELLO_MSG) { + printf("Received hello message from %s\n",inet_ntoa(ip->ip_src)); + } + else if(xmsg.type() == Xroute::LSA_MSG) { + printf("Received LSA_MSG from %s\n", inet_ntoa(ip->ip_src)); + processLSA(xmsg); + // 5. rebroadcast this LSA + } + else { + printf("Unknown msg type \n"); + } + } + } + + // std::string msg = sendHello(); + std::string msg = sendLSA(); + c++; + + if(c>1) { + WritablePacket *q = Packet::make(1); + output(port).push(q); + return; + } + + printf("\n**********************\n getting neighbors c :%d\n", c); + + neighbor_broadcast(msg); + + printf("\n**********************\n"); + +} + + +CLICK_ENDDECLS +EXPORT_ELEMENT(XIAOverlayRouted) +ELEMENT_MT_SAFE(XIAOverlayRouted) +ELEMENT_LIBS(-lprotobuf -L../../api/lib -ldagaddr) diff --git a/click/elements/xia/xiaoverlayrouted.hh b/click/elements/xia/xiaoverlayrouted.hh new file mode 100644 index 000000000..067a831f6 --- /dev/null +++ b/click/elements/xia/xiaoverlayrouted.hh @@ -0,0 +1,163 @@ +#ifndef CLICK_XIAOVERLAYROUTED_HH +#define CLICK_XIAOVERLAYROUTED_HH +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../userlevel/xroute.pb.h" + +using namespace std; + +CLICK_DECLS + +#define F_CORE_ROUTER 0x0002 // node is an internal router +#define F_EDGE_ROUTER 0x0004 // node is an edge router +#define F_CONTROLLER 0x0008 // node is a controller +#define F_IP_GATEWAY 0x0010 // router is a dual stack router +#define F_STATIC_ROUTE 0x0100 // route entry was added manually and should not expire + +// Main loop iterates every 1000 usec = 1 ms = 0.001 sec +#define MAIN_LOOP_USEC 1000 +#define MAIN_LOOP_MSEC 50 // .05 sec +#define RECV_ITERS 2 +#define HELLO_ITERS 2 +#define LSA_ITERS 8 +#define CALC_DIJKSTRA_INTERVAL 4 +#define MAX_HOP_COUNT 50 +#define MAX_XID_SIZE 64 +#define MAX_DAG_SIZE 512 + +#define XR_OK 0 +#define XR_NOT_CONNECTED -1 +#define XR_ALREADY_CONNECTED -2 +#define XR_CLICK_ERROR -3 +#define XR_ROUTE_EXISTS -4 +#define XR_ROUTE_DOESNT_EXIST -5 +#define XR_NOT_XIA -6 +#define XR_ROUTER_NOT_SET -7 +#define XR_BAD_HOSTNAME -8 +#define XR_INVALID_XID -9 + +#define TOTAL_SPECIAL_CASES 8 +#define DESTINED_FOR_DISCARD -1 +#define DESTINED_FOR_LOCALHOST -2 +#define DESTINED_FOR_DHCP -3 +#define DESTINED_FOR_BROADCAST -4 +#define REDIRECT -5 +#define UNREACHABLE -6 +#define FALLBACK -7 + +typedef struct { + std::string xid; + std::string nextHop; + unsigned short port; + unsigned long flags; +} XIARouteEntry; + +typedef struct { + std::string dest; // destination AD or HID + std::string nextHop; // nexthop HID + int32_t port; // interface (outgoing port) + uint32_t flags; // flag +} RouteEntry; + +typedef struct { + std::string AD; // neigbor AD + std::string HID; // neighbor HID + std::string SID; // neighbor SID + std::string addr; // overlay addr + int32_t cost; // link cost + int32_t port; // interface (outgoing port) +} NeighborEntry; + +typedef struct { + std::string dest; // destination AD or HID + int32_t num_neighbors; // number of neighbors of dest AD + std::vector neighbor_list; // neighbor AD list + + bool checked; // used for calculating the shortest path + int32_t cost; // cost from myAD to destAD + std::string prevNode; // previous node along the shortest path from myAD to destAD + +} NodeStateEntry; // extracted from incoming LSA + + +typedef struct RouteState { + int32_t sock; // socket for routing process + + char myAD[MAX_XID_SIZE]; // this router AD + char myOverlaySID[MAX_XID_SIZE]; // this router overlay SID + char myHID[MAX_XID_SIZE]; // this router HID + char my4ID[MAX_XID_SIZE]; // not used + + uint32_t flags; + std::string dual_router_AD; // AD (with dual router) -- default AD for 4ID traffic + int32_t num_neighbors; // number of neighbor routers + int32_t hello_lsa_ratio; // frequency ratio of hello:lsa (for timer purpose) + int32_t calc_dijstra_ticks; + + std::map ADrouteTable; // map DestAD to route entry + std::map HIDrouteTable; // map DestHID to route entry + std::map neighborTable; // map neighborAD to neighbor entry + std::map networkTable; // map DestAD to NodeState entry + +} RouteState; + + + +class XIAOverlayRouted : public Element { + + void add_handlers(); + String itoa(signed i); + std::string sendHello(); + std::string sendLSA(); + int processLSA(const Xroute::XrouteMsg &msg); + void updateClickRoutingTable(); + int updateRoute(string cmd, const std::string &xid, int port, + const std::string &next, unsigned long flags); + void calcShortestPath(); + void neighbor_broadcast(std::string msg); + void _push_msg(std::string msg, String dst, int port); + void printRoutingTable(); + + protected: + static int add_neighbor(const String &conf, Element *e, void *thunk, ErrorHandler *errh); + + RouteState route_state; + // XIARouter xr; + String _hostname; + int c; + + public: + + XIAOverlayRouted(); + ~XIAOverlayRouted(); + + const char *class_name() const { return "XIAOverlayRouted"; } + const char *port_count() const { return "1/4"; } + const char *processing() const { return PUSH; } + + void push(int, Packet *); + + + + // int getNeighbors(std::vector &neighbors); +}; + +CLICK_ENDDECLS +#endif diff --git a/click/elements/xia/xiaoverlaysocket.cc b/click/elements/xia/xiaoverlaysocket.cc index 04ca7ca50..dc16632a5 100644 --- a/click/elements/xia/xiaoverlaysocket.cc +++ b/click/elements/xia/xiaoverlaysocket.cc @@ -68,8 +68,6 @@ XIAOverlaySocket::selected(int fd, int) else { // datagram server, find out who we are talking to len = recvfrom(_active, _rq->data(), _rq->length(), MSG_TRUNC, (struct sockaddr *)&from, &from_len); - printf("XIAOverlaySocket::selected rcvd pkt of len %d\n", len); - printf("from: %s:%d\n", IPAddress(from.in.sin_addr).unparse().c_str(), ntohs(from.in.sin_port)); if (_family == AF_INET && !allowed(IPAddress(from.in.sin_addr))) { if (_verbose) @@ -127,12 +125,10 @@ XIAOverlaySocket::selected(int fd, int) int XIAOverlaySocket::write_packet(Packet *p) { - int len; - - - assert(_active >= 0); + int len; + assert(_active >= 0); - while (p->length()) { + while (p->length()) { struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_port = DST_PORT_ANNO(p); @@ -148,35 +144,36 @@ XIAOverlaySocket::write_packet(Packet *p) printf("XIAOverlaySocket: ERROR xia hdr != p->data\n"); } - if (_socktype != SOCK_DGRAM) { - click_chatter("XIAOverlaySocket: ERROR: not datagram socket"); - p->kill(); - return -1; - } - len = sendto(_active, p->data(), p->length(), 0, - (struct sockaddr *)&dest, sizeof(dest)); - // error - if (len < 0) { - // out of memory or would block - if (errno == ENOBUFS || errno == EAGAIN) { - return -1; - } else if (errno == EINTR) { - continue; - } else { - if(_verbose) { - click_chatter("%s: %s", declaration().c_str(), - strerror(errno)); - } - close_active(); - break; - } - } else { - // this segment OK - p->pull(len); - } + if (_socktype != SOCK_DGRAM) { + click_chatter("XIAOverlaySocket: ERROR: not datagram socket"); + p->kill(); + return -1; } - p->kill(); - return 0; + printf("Sending len %d\n", p->length()); + len = sendto(_active, p->data(), p->length(), 0, + (struct sockaddr *)&dest, sizeof(dest)); + // error + if (len < 0) { + // out of memory or would block + if (errno == ENOBUFS || errno == EAGAIN) { + return -1; + } else if (errno == EINTR) { + continue; + } else { + if(_verbose) { + click_chatter("%s: %s", declaration().c_str(), + strerror(errno)); + } + close_active(); + break; + } + } else { + // this segment OK + p->pull(len); + } + } + p->kill(); + return 0; } void diff --git a/click/elements/xia/xiaxidroutetable.cc b/click/elements/xia/xiaxidroutetable.cc index 8b7e395af..a7390f73e 100644 --- a/click/elements/xia/xiaxidroutetable.cc +++ b/click/elements/xia/xiaxidroutetable.cc @@ -9,6 +9,12 @@ #include #include #include + +#include +#include +#include + + #if CLICK_USERLEVEL #include #include @@ -16,11 +22,24 @@ #include #include + + #endif CLICK_DECLS XIAXIDRouteTable::XIAXIDRouteTable(): _drops(0) { + char *hostname = (char *)malloc(32); + assert(hostname); + FILE *f = fopen("etc/address.conf", "r"); + if (!f) { + printf("Failed to open address.conf \n"); + return; + } + fscanf(f,"%s", hostname); + fclose(f); + + _hostname = String(hostname, strlen(hostname)); } XIAXIDRouteTable::~XIAXIDRouteTable() @@ -31,8 +50,6 @@ XIAXIDRouteTable::~XIAXIDRouteTable() int XIAXIDRouteTable::configure(Vector & /*conf*/, ErrorHandler * /*errh*/) { - //click_chatter("XIAXIDRouteTable: configuring %s\n", this->name().c_str()); - _principal_type_enabled = 1; _rtdata.port = -1; @@ -68,6 +85,8 @@ XIAXIDRouteTable::add_handlers() add_read_handler("list", list_routes_handler, 0); add_write_handler("enabled", write_handler, (void *)PRINCIPAL_TYPE_ENABLED); add_read_handler("enabled", read_handler, (void *)PRINCIPAL_TYPE_ENABLED); + add_write_handler("addIP", add_ip_handler, 0); + add_read_handler("listIP", list_ip_handler, 0); } String @@ -96,7 +115,7 @@ XIAXIDRouteTable::write_handler(const String &str, Element *e, void *thunk, Erro } void -XIAXIDRouteTable::add_entry_to_tbl_str(String& tbl, String xid, +XIAXIDRouteTable::add_entry_to_tbl_str(Element *e, String& tbl, String xid, XIARouteData* xrd) { // XID @@ -117,29 +136,43 @@ XIAXIDRouteTable::add_entry_to_tbl_str(String& tbl, String xid, } String -XIAXIDRouteTable::list_routes_handler(Element *e, void * /*thunk */) +XIAXIDRouteTable::list_routes_handler(Element *e, void *thunk) { XIAXIDRouteTable* table = static_cast(e); XIARouteData *xrd = &table->_rtdata; // get the default route String tbl; - add_entry_to_tbl_str(tbl, "-", xrd); + add_entry_to_tbl_str(e, tbl, "-", xrd); // get the rest for(auto& it : table->_rts) { String xid = it.first.unparse(); xrd = it.second; - add_entry_to_tbl_str(tbl, xid, xrd); + add_entry_to_tbl_str(e, tbl, xid, xrd); } return tbl; } +String +XIAXIDRouteTable::list_ip_handler(Element *e, void *) +{ + + XIAXIDRouteTable* table = static_cast(e); + String ntable; + HashTable::iterator it; + for(it = table->_nts.begin(); it != table->_nts.end(); it++) { + ntable += String(it->first + "," + it->second->AD->c_str() + "," + + it->second->SID->c_str() + ";"); + } + + return ntable; +} + int XIAXIDRouteTable::set_handler(const String &conf, Element *e, void *thunk, ErrorHandler *errh) { // handle older style route entries - String str_copy = conf; String xid_str = cp_shift_spacevec(str_copy); @@ -230,9 +263,64 @@ XIAXIDRouteTable::set_handler4(const String &conf, Element *e, void *thunk, Erro return 0; } +int +XIAXIDRouteTable::add_ip_handler(const String &conf, Element *e, void *thunk, ErrorHandler *errh) +{ + XIAXIDRouteTable* table = static_cast(e); + + Vector args; + String xid_str, ipstr; + + cp_argvec(conf, args); + + if (args.size() != 2) { + printf("1 %ld\n", args.size()); + return errh->error("Invalid route(need 2 entries): ", conf.c_str()); + } + + if (!cp_string(args[0], &ipstr)) { + printf("3\n"); + return errh->error("Invalid ipaddr arg"); + } + + if (!cp_string(args[1], &xid_str)) { + printf("2\n"); + return errh->error("Invalid xid arg"); + } + + HashTable::iterator it = table->_nts.find(ipstr); + XIAXIDAddr *n; + if(it == table->_nts.end()) { + n = new XIAXIDAddr(); + table->_nts[ipstr] = n; + } + else { + n = it->second; + } + + std::string *s = new std::string(xid_str.c_str()); + + if(xid_str.starts_with("AD")) { + n->AD = s; + printf("XIAXIDRouteTable: Added AD for %s : %s\n", ipstr.c_str(), table->_nts[ipstr]->AD->c_str()); + } + else if(xid_str.starts_with("HID")) + { + n->HID = s; + printf("XIAXIDRouteTable: Added HID for %s : %s\n", ipstr.c_str(), table->_nts[ipstr]->HID->c_str()); + } + else if(xid_str.starts_with("SID")) { + n->SID = s; + printf("XIAXIDRouteTable: Added SID for %s : %s\n", ipstr.c_str(), table->_nts[ipstr]->SID->c_str()); + } + + return 0; +} + int XIAXIDRouteTable::set_udpnext(const String &conf, Element *e, void *thunk, ErrorHandler *errh) { + XIAXIDRouteTable* table = static_cast(e); bool add_mode = !thunk; Vector args; @@ -264,8 +352,75 @@ XIAXIDRouteTable::set_udpnext(const String &conf, Element *e, void *thunk, Error } String ipaddrstr = nxthop.substring(0, separator_offset); String portstr = nxthop.substring(separator_offset+1); - printf("XIAXIDRouteTable: ip: %s, port: %s\n", - ipaddrstr.c_str(), portstr.c_str()); + + String ename = table->_hostname + String("/xrc/n/proc/rt_IP"); + Element *ne = e->router()->find(ename); + if(ne) { + printf("XIAXIDRoutetable: Calling write \n"); + int ret = HandlerCall::call_write(ne, "addIP", ipaddrstr + "," + xid_str); + if (ret) + return errh->error("Failed to call write\n"); + } + else { + printf("Element %s not found \n", ename.c_str()); + return errh->error("Failed to find element : \n", ename.c_str()); + } + + + if(args.size() > 3) { + int flags; + // XIARouteData *xrd = &table->_rtdata; + if (!cp_integer(args[3], &flags)) + return errh->error("invalid flags: ", conf.c_str()); + + printf("XIAXIDRouteTable: Going into the neighbor block \n"); + if(flags == NEIGHBOR) + { + // Vector ve = e->router()->elements(); + // for(int i=0; iname().c_str()); + // } + + String ename = table->_hostname + String("/xrc/n/proc/rt_IP"); + Element *ne = e->router()->find(ename); + if(ne) { + String result = HandlerCall::call_read(ne, "listIP"); + std::string rstr(result.c_str (), result.length()); + + std::string::size_type beg = 0; + String ad, sid; + for (auto end = 0; (end = rstr.find(';', end)) != std::string::npos; end++) + { + std::string n(rstr.substr(beg, end - beg)); + Vectorargs; + String c(n.c_str()); + cp_argvec(c, args); + if(args.size() != 3) { + return errh->error("Not all args"); + } + if(args[0].equals(ipaddrstr)) { + cp_string(args[1], &ad); + cp_string(args[2], &sid); + break; + } + beg = end + 1; + } + String rname = "rd/rd"; + Element *re = e->router()->find(rname); + if(re) { + String nentry(ipaddrstr + "," + ad + "," + sid + "," + std::to_string(port).c_str()); + if(HandlerCall::call_write(re, "neighbor", nentry)) { + return errh->error("Failed to write to xrouted"); + } + } + + } + else { + return errh->error("Element not found : ", ename.c_str()); + } + } + } + struct in_addr ipaddr; if(inet_aton(ipaddrstr.c_str(), &ipaddr) == 0) { return errh->error("Invalid ipaddr: ", ipaddrstr.c_str()); @@ -309,6 +464,8 @@ XIAXIDRouteTable::set_udpnext(const String &conf, Element *e, void *thunk, Error xrd->nexthop_in = std::move(addr); table->_rts[xid] = xrd; } + + return 0; } @@ -377,7 +534,7 @@ XIAXIDRouteTable::load_routes_handler(const String &conf, Element *e, void *, Er c++; } - click_chatter("loaded %d entries", c); + printf("loaded %d entries", c); return 0; #elif CLICK_LINUXMODLE @@ -398,7 +555,7 @@ XIAXIDRouteTable::load_routes_handler(const String &conf, Element *e, void *, Er file_read(filp, curpos, buf, 1020); char * eol = strchr(buf, '\n'); if (eol==NULL) { - click_chatter("Error at %s %d\n", __FUNCTION__, __LINE__); + printf("Error at %s %d\n", __FUNCTION__, __LINE__); break; } curpos+=(eol+1-buf); @@ -407,14 +564,14 @@ XIAXIDRouteTable::load_routes_handler(const String &conf, Element *e, void *, Er continue; if (set_handler(buf, e, 0, errh) != 0) { - click_chatter("Error at %s %d\n", __FUNCTION__, __LINE__); + printf("Error at %s %d\n", __FUNCTION__, __LINE__); return -1; } c++; } set_fs(old_fs); - click_chatter("XIA routing table loaded %d entries", c); + printf("XIA routing table loaded %d entries", c); return 0; #endif } @@ -460,7 +617,7 @@ XIAXIDRouteTable::generate_routes_handler(const String &conf, Element *e, void * struct click_xia_xid xid_d; xid_d.type = xid_type; - if (port<0) click_chatter("Random %d ports", -port); + if (port<0) printf("Random %d ports", -port); for (int i = 0; i < count; i++) { @@ -485,7 +642,7 @@ XIAXIDRouteTable::generate_routes_handler(const String &conf, Element *e, void * #else *reinterpret_cast(xid) = static_cast(prandom32(&state)); if (i%5000==0) - click_chatter("random value %x", *reinterpret_cast(xid)); + printf("random value %x", *reinterpret_cast(xid)); #endif xid += sizeof(uint32_t); } @@ -504,14 +661,14 @@ XIAXIDRouteTable::generate_routes_handler(const String &conf, Element *e, void * random = random % (-port); xrd->port = random; if (i%5000 == 0) - click_chatter("Random port for XID %s #%d: %d ",XID(xid_d).unparse_pretty(e).c_str(), i, random); + printf("Random port for XID %s #%d: %d ",XID(xid_d).unparse_pretty(e).c_str(), i, random); } else xrd->port = port; table->_rts[XID(xid_d)] = xrd; } - click_chatter("generated %d entries", count); + printf("generated %d entries", count); return 0; } diff --git a/click/elements/xia/xiaxidroutetable.hh b/click/elements/xia/xiaxidroutetable.hh index 76ee2a99d..0bcef2104 100644 --- a/click/elements/xia/xiaxidroutetable.hh +++ b/click/elements/xia/xiaxidroutetable.hh @@ -38,34 +38,52 @@ so use the XIACheckDest element before using this element. #define REDIRECT -5 #define UNREACHABLE -6 #define FALLBACK -7 +#define NEIGHBOR 263 +//7 #define XIA_UDP_NEXTHOP 5 +#define MAX_NEIGHBOR_CNT 1024 //todo: arbitrary value at this point + enum { PRINCIPAL_TYPE_ENABLED, ROUTE_TABLE_HID, FWD_TABLE_DAG, XCACHE_SID }; typedef struct { - int port; - unsigned flags; - XID *nexthop; - std::unique_ptr nexthop_in; + int port; + unsigned flags; + XID *nexthop; + std::unique_ptr nexthop_in; } XIARouteData; + +typedef struct { + std::string *AD; + std::string *HID; + std::string *SID; +} XIAXIDAddr; + +typedef struct { + String *addr; // ip:port + int iface; // outgoing iface to the neighbor + String *AD; +} XIAXIDNeighbor; + class XIAXIDRouteTable : public Element { public: XIAXIDRouteTable(); ~XIAXIDRouteTable(); - const char *class_name() const { return "XIAXIDRouteTable"; } - const char *port_count() const { return "-/-"; } - const char *processing() const { return PUSH; } + const char *class_name() const { return "XIAXIDRouteTable"; } + const char *port_count() const { return "-/-"; } + const char *processing() const { return PUSH; } int configure(Vector &, ErrorHandler *); void add_handlers(); void push(int in_ether_port, Packet *); - int set_enabled(int e); - int get_enabled(); + int set_enabled(int e); + int get_enabled(); + void printRoutingTable(); protected: int lookup_route(Packet *); @@ -73,21 +91,27 @@ protected: static int set_handler(const String &conf, Element *e, void *thunk, ErrorHandler *errh); static int set_handler4(const String &conf, Element *e, void *thunk, ErrorHandler *errh); - static int set_udpnext(const String &conf, Element *e, void *thunk, ErrorHandler *errh); + static int add_ip_handler(const String &conf, Element *e, void *thunk, ErrorHandler *errh); + static int set_udpnext(const String &conf, Element *e, void *thunk, ErrorHandler *errh); static int remove_handler(const String &conf, Element *e, void *, ErrorHandler *errh); static int load_routes_handler(const String &conf, Element *e, void *, ErrorHandler *errh); static int generate_routes_handler(const String &conf, Element *e, void *, ErrorHandler *errh); - static String read_handler(Element *e, void *thunk); - static int write_handler(const String &str, Element *e, void *thunk, ErrorHandler *errh); + static String read_handler(Element *e, void *thunk); + static int write_handler(const String &str, Element *e, void *thunk, ErrorHandler *errh); - static void add_entry_to_tbl_str(String& tbl, String xid, XIARouteData* xrd); + static void add_entry_to_tbl_str(Element *e, String& tbl, String xid, XIARouteData* xrd); static String list_routes_handler(Element *e, void *thunk); + static String list_neighbor_handler(Element *e, void *); + static String list_ip_handler(Element *e, void *); - HashTable _rts; - XIARouteData _rtdata; + HashTable _rts; + HashTable _nts; + XIARouteData _rtdata; uint32_t _drops; + String _hostname; + std::vector _ntable; - int _principal_type_enabled; + int _principal_type_enabled; }; CLICK_ENDDECLS diff --git a/click/userlevel/Makefile.in b/click/userlevel/Makefile.in index 49f0771cc..52ebdafdd 100644 --- a/click/userlevel/Makefile.in +++ b/click/userlevel/Makefile.in @@ -72,7 +72,7 @@ GENERIC_OBJS = string.o straccum.o nameinfo.o \ routerthread.o router.o master.o timerset.o selectset.o handlercall.o notifier.o \ integers.o md5.o crc32.o in_cksum.o iptable.o \ archive.o userutils.o driver.o \ - xid.o xidpair.o xidtuple.o xiapath.o xiaheader.o xiautil.o xia.pb.o \ + xid.o xidpair.o xidtuple.o xiapath.o xiaheader.o xiautil.o xia.pb.o xroute.pb.o\ xiasecurity.o \ xiamigrate.o \ xiarendezvous.o \ @@ -141,6 +141,9 @@ all: $(INSTALLPROGS) $(INSTALLLIBS) xia.pb.cc: xia.proto protoc --cpp_out=. xia.proto +xroute.pb.cc: xroute.proto + protoc --cpp_out=. xroute.proto + ifneq ($(MAKECMDGOALS),clean) -include $(ELEMENTSCONF).mk endif @@ -167,6 +170,8 @@ $(ELEMENTSCONF).cc: $(ELEMENTSCONF).conf $(CLICK_BUILDTOOL) $(call verbose_cmd,$(CLICK_BUILDTOOL) elem2export < $(ELEMENTSCONF).conf >,CREATE,$(ELEMENTSCONF).cc) @rm -f $(ELEMENTSCONF).d echo '#include "xia.pb.h"' | cat - $(ELEMENTSCONF).cc > temp && mv temp $(ELEMENTSCONF).cc + echo '#include "xroute.pb.h"' | cat - $(ELEMENTSCONF).cc > temp && mv temp $(ELEMENTSCONF).cc + DEPFILES := $(wildcard *.d) ifneq ($(DEPFILES),) @@ -189,7 +194,7 @@ uninstall: clean: rm -f *.d *.o $(INSTALLPROGS) $(ELEMENTSCONF).mk $(ELEMENTSCONF).cc elements.conf elements.csmk libclick.a - rm -f xia.pb.h xia.pb.cc + rm -f xia.pb.h xia.pb.cc xroute.pb.cc @-for i in $(INSTALLPROGS); do rm -f ../bin/$$i; done clean-lib: rm -f $(LIBOBJS) libclick.a diff --git a/click/userlevel/xroute.proto b/click/userlevel/xroute.proto new file mode 100644 index 000000000..5b9206b04 --- /dev/null +++ b/click/userlevel/xroute.proto @@ -0,0 +1,91 @@ +syntax = "proto2"; +/* +** xrouted message definitions +*/ + +package Xroute; +//syntax = "proto2"; + +enum constants { + XROUTE_PROTO_VERSION = 1; +} + +message XID { + required uint32 type = 1; // should use the XID type values from xia.h + required bytes id = 2; // must be 20 bytes long +} + +message Node { + required XID ad = 1; + optional XID hid = 2; + optional XID sid = 3; + optional uint32 flags = 4; +} + +message TableEntry { + required Node node = 1; + required uint32 interface = 2; + optional uint32 flags = 3; +} + +message HelloMsg { + required Node node = 1; + optional uint32 flags = 2; +} + +message LSAMsg { + required Node node = 1; + optional uint32 flags = 2; + repeated Node peers = 3; +} + +message HostJoinMsg { + required string hid = 1; + required uint32 interface = 2; + optional uint32 flags = 3; +} + +// FIXME: make this use the XID type at some point +message HostLeaveMsg { + required string hid = 1; +} + +message TableUpdateMsg { + required Node from = 1; + required Node to = 2; + repeated TableEntry route = 3; +} + +message GlobalLSAMsg { + required Node from = 1; +} + +message ConfigMsg { + required string ad = 1; + required string controller_dag = 2; +} + +enum msg_type { + HELLO_MSG = 1; // local router hello msg. still needed? + LSA_MSG = 2; // router announcement -> controller + HOST_JOIN_MSG = 3; // add host route from xnetjd + HOST_LEAVE_MSG = 4; // host leaving network + TABLE_UPDATE_MSG = 5; // new tables from controller -> router + GLOBAL_LSA_MSG = 6; // lsa between controllers in different ADs + CONFIG_MSG = 7; // router configuration info from xnetjd +} + +message XrouteMsg { + required uint32 version = 1; + required msg_type type = 2; + + oneof payload { + HelloMsg hello = 3; + LSAMsg lsa = 4; + TableUpdateMsg table_update = 5; + GlobalLSAMsg global_lsa = 6; + HostJoinMsg host_join = 7; + HostLeaveMsg host_leave = 8; + ConfigMsg config = 9; + } +} diff --git a/daemons/common/XIARouter.hh b/daemons/common/XIARouter.hh index f285e7fb2..3a92b4b3e 100644 --- a/daemons/common/XIARouter.hh +++ b/daemons/common/XIARouter.hh @@ -90,6 +90,7 @@ public: int setRoute(const std::string &xid, int port, const std::string &next, unsigned long flags); int delRoute(const std::string &xid); + const char *cserror(); private: bool _connected; diff --git a/daemons/xrouted/xrouted.cc b/daemons/xrouted/xrouted.cc index b15b2b045..3e21c63cb 100644 --- a/daemons/xrouted/xrouted.cc +++ b/daemons/xrouted/xrouted.cc @@ -80,8 +80,6 @@ int sendHello() sid->set_id(n_sid.id(), XID_SIZE); -// printf("sending %s\n", msg.DebugString().c_str()); - msg.SerializeToString(&message); buflen = message.length(); @@ -137,8 +135,6 @@ int sendLSA() hid->set_id(p_hid.id(), XID_SIZE); } -// printf("sending %s\n", msg.DebugString().c_str()); - msg.SerializeToString(&message); buflen = message.length(); @@ -264,8 +260,6 @@ int processLSA(const Xroute::XrouteMsg& msg) string neighborAD, neighborHID, myAD; string destAD, destHID; -// printf("processLSA: %s\n", lsa.DebugString().c_str()); - // fix me once we don't need to rebroadcast the lsa const Xroute::LSAMsg& lsa = msg.lsa(); @@ -288,8 +282,6 @@ int processLSA(const Xroute::XrouteMsg& msg) return 1; } - - map::iterator it = route_state.networkTable.find(destAD); if(it != route_state.networkTable.end()) { // For now, delete this dest AD entry in networkTable diff --git a/daemons/xrouted/xrouted.hh b/daemons/xrouted/xrouted.hh index 1a8f96f7b..04993160d 100644 --- a/daemons/xrouted/xrouted.hh +++ b/daemons/xrouted/xrouted.hh @@ -41,10 +41,6 @@ using namespace std; #define MAX_XID_SIZE 64 #define MAX_DAG_SIZE 512 - - - - #define BFID "FID:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" #define SID_XROUTE "SID:1110000000000000000000000000000000001112" #define NULL_4ID "IP:4500000000010000fafa00000000000000000000" diff --git a/tools/overlay/client.conf b/tools/overlay/client.conf new file mode 100644 index 000000000..b414f0920 --- /dev/null +++ b/tools/overlay/client.conf @@ -0,0 +1,20 @@ +[c2] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf192 +ControlAddress = 10.0.1.133 +ControlPort = 8295 +Routers = r2 +Interfaces = ens34 +Default = r2 +ServerDag = RE AID:69a4e068880cd40549405dfda6e794b0c7fdf192 + +[c1] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf195 +ControlAddress = 10.0.1.130 +ControlPort = 8295 +# Routers = r1,r3 +# Interfaces = ens40,ens41 +Routers = r1 +Interfaces = ens40 +Default = r1 +ServerDag = RE AD:1ff8cb8d5d0afeee9e3af7dfc0099a52e4764916 HID:c71d04d17f225ffc71ba6bf31a673e51386c533c AID:69a4e068880cd40549405dfda6e794b0c7fdf192 +Mobile = true diff --git a/tools/overlay/clientconfig.proto b/tools/overlay/clientconfig.proto new file mode 100644 index 000000000..268954ca0 --- /dev/null +++ b/tools/overlay/clientconfig.proto @@ -0,0 +1,15 @@ +syntax = "proto2"; + +package clientconfig; + +message Config { + required string name = 1; + required string AID = 2; + required string ipaddr = 3; + required string iface = 4; + required string port = 5; + required string AD = 6; + required string HID = 7; + required string serverdag = 8; +} + diff --git a/tools/overlay/conf/mobility/client_mobility.conf b/tools/overlay/conf/mobility/client_mobility.conf new file mode 100644 index 000000000..f26400a40 --- /dev/null +++ b/tools/overlay/conf/mobility/client_mobility.conf @@ -0,0 +1,18 @@ +[c2] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf192 +ControlAddress = 10.0.1.133 +ControlPort = 8295 +Routers = r2 +Interfaces = ens34 +Default = r2 +ServerDag = RE AID:69a4e068880cd40549405dfda6e794b0c7fdf192 + +[c1] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf195 +ControlAddress = 10.0.1.130 +ControlPort = 8295 +Routers = r1,r3 +Interfaces = ens40,ens41 +Default = r1 +ServerDag = RE AD:1ff8cb8d5d0afeee9e3af7dfc0099a52e4764916 HID:c71d04d17f225ffc71ba6bf31a673e51386c533c AID:69a4e068880cd40549405dfda6e794b0c7fdf192 +Mobile = true diff --git a/tools/overlay/conf/mobility/mobility.conf b/tools/overlay/conf/mobility/mobility.conf new file mode 100644 index 000000000..660b26222 --- /dev/null +++ b/tools/overlay/conf/mobility/mobility.conf @@ -0,0 +1,24 @@ +[r1] +ControlAddress = 10.0.1.129 +Interfaces = ens35,ens39,ens34,ens40 +HostInterface = ens35 +HostAddr = 10.0.2.129 +NameServer = true +Route_r2 = ens39 -> ens34:r2 +Route_r3 = ens40 -> ens39:r3 + +[r2] +ControlAddress = 10.0.1.132 +Interfaces = ens39,ens40,ens34,ens41 +HostInterface = ens39 +HostAddr = 10.0.4.129 +Route_r1 = ens34 -> ens39:r1 +Route_r3 = ens41 -> ens40:r3 + +[r3] +ControlAddress = 10.0.1.134 +Interfaces = ens38,ens39,ens40,ens41 +HostInterface = ens41 +HostAddr = 10.0.3.134 +Route_r1 = ens39 -> ens40:r1 +Route_r2 = ens40 -> ens41:r2 \ No newline at end of file diff --git a/tools/overlay/conf/server_dag/client_server_dag.conf b/tools/overlay/conf/server_dag/client_server_dag.conf new file mode 100644 index 000000000..e5c073a73 --- /dev/null +++ b/tools/overlay/conf/server_dag/client_server_dag.conf @@ -0,0 +1,17 @@ +[c2] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf192 +ControlAddress = 10.0.1.133 +ControlPort = 8295 +Routers = r2 +Interfaces = ens34 +Default = r2 +ServerDag = RE AID:69a4e068880cd40549405dfda6e794b0c7fdf192 + +[c1] +AID = AID:69a4e068880cd40549405dfda6e794b0c7fdf195 +ControlAddress = 10.0.1.130 +ControlPort = 8295 +Routers = r1 +Interfaces = ens40 +Default = r1 +ServerDag = RE ( AD:cc8249bfea9de0461ae4127ebcd3b0ed0b6338e9 HID:813f0679821b6ba19602daf5a0471d62b721b4eb ) AD:1ff8cb8d5d0afeee9e3af7dfc0099a52e4764916 HID:c71d04d17f225ffc71ba6bf31a673e51386c533c AID:69a4e068880cd40549405dfda6e794b0c7fdf192 diff --git a/tools/overlay/conf/server_dag/server_dag.conf b/tools/overlay/conf/server_dag/server_dag.conf new file mode 100644 index 000000000..4a2f54daf --- /dev/null +++ b/tools/overlay/conf/server_dag/server_dag.conf @@ -0,0 +1,25 @@ +[r1] +ControlAddress = 10.0.1.129 +Interfaces = ens35,ens39,ens34,ens40 +HostInterface = ens35 +HostAddr = 10.0.2.129 +NameServer = true +#Route_r2 = ens39 -> ens34:r2 +Route_r3 = ens40 -> ens39:r3 + +[r2] +ControlAddress = 10.0.1.132 +Interfaces = ens39,ens40,ens34,ens41 +HostInterface = ens39 +HostAddr = 10.0.4.129 +#Route_r1 = ens34 -> ens39:r1 +Route_r3 = ens41 -> ens40:r3 +Route_r1 = ens41 -> ens40:r3 + +[r3] +ControlAddress = 10.0.1.134 +Interfaces = ens38,ens39,ens40 +HostInterface = ens39 +HostAddr = 10.0.2.130 +Route_r1 = ens39 -> ens40:r1 +Route_r2 = ens40 -> ens41:r2 \ No newline at end of file diff --git a/tools/overlay/demo.conf b/tools/overlay/demo.conf index 05ac2b52e..ca7f2bd1d 100644 --- a/tools/overlay/demo.conf +++ b/tools/overlay/demo.conf @@ -1,13 +1,24 @@ [r1] -ControlAddress = 172.16.148.166 -Interfaces = ens33,ens38 -HostInterface = ens33 +ControlAddress = 10.0.1.128 +Interfaces = ens35,ens39,ens34,ens40 +HostInterface = ens35 +HostAddr = 10.0.2.128 NameServer = true -Route_r2 = ens38 -> ens33:r2 +Route_r2 = ens39 -> ens34:r2 +Route_r3 = ens40 -> ens39:r3 [r2] -ControlAddress = 172.16.252.131 -Interfaces = ens33,ens38 -HostInterface = ens38 -Route_r1 = ens33 -> ens38:r1 -Xcache = true +ControlAddress = 10.0.1.130 +Interfaces = ens39,ens40,ens34,ens41 +HostInterface = ens39 +HostAddr = 10.0.4.129 +Route_r1 = ens34 -> ens39:r1 +# Route_r3 = ens41 -> ens40:r3 + +[r3] +ControlAddress = 10.0.1.132 +Interfaces = ens38,ens39,ens40,ens41 +HostInterface = ens41 +HostAddr = 10.0.3.134 +Route_r1 = ens39 -> ens40:r1 +# Route_r2 = ens40 -> ens41:r2 diff --git a/tools/overlay/events.conf b/tools/overlay/events.conf new file mode 100644 index 000000000..d1832f251 --- /dev/null +++ b/tools/overlay/events.conf @@ -0,0 +1,10 @@ +[e1] +add_r1 = r2, r3 +add_r2 = r1 +add_r3 = r1 +duration = 20 + +[e2] +remove_r1 = r3 +remove_r3 = r1 +duration = 30 \ No newline at end of file diff --git a/tools/overlay/routerclick.py b/tools/overlay/routerclick.py index 96f38e472..63d9061a4 100644 --- a/tools/overlay/routerclick.py +++ b/tools/overlay/routerclick.py @@ -42,13 +42,48 @@ def to_string(self): for index in range(4): if (index < num_interfaces): (iface_name, ipaddr, macaddr) = self.interfaces[index] - rstr += '\nosock{}::XIAOverlaySocket("UDP", {}, {}, SNAPLEN 65536) -> [{}]{}[{}] -> osock{};\n'.format(index, ipaddr, 8770, index, self.name, index, index) + rstr += '\nosock{}::XIAOverlaySocket("UDP", {}, {}, SNAPLEN 65536) -> [{}]{}[{}] -> osock{};'.format(index, ipaddr, 8770, index, self.name, index, index) else: - rstr += '\nIdle -> [{}]{}[{}] -> Discard;\n'.format( - index, self.name, index) + rstr += '\nIdle -> [{}]{}[{}] -> Discard;\n'.format(index, self.name, index) + + rstr += '\n rd :: XIAOverlayRouter();\n' + for index in range(4): + if (index < num_interfaces): + (iface_name, ipaddr, macaddr) = self.interfaces[index] + rstr += 'rsock{}::XIAOverlaySocket("UDP", {}, {}, SNAPLEN 65536) -> rd;\n'.format(index, ipaddr, 8772) + + rstr += '\n' + for index in range(4): + if (index < num_interfaces): + rstr += 'rd[{}] -> rsock{};\n'.format(index, index) + + + # rstr += '\n' + # for index in range(4): + # if (index < num_interfaces): + # (iface_name, ipaddr, macaddr) = self.interfaces[index] + # rstr += 'rsock{}::XIAOverlaySocket("UDP", {}, {}, SNAPLEN 65536) -> rd{}::XIAOverlayRouted();\n'.format(index, ipaddr, 8772, index, index) + + # rstr += '\n' + # for index in range(4): + # if (index < num_interfaces): + # for i in range(0,3): + # if (i < num_interfaces): + # rstr += 'rd{}[{}] -> of{}::XIAOverlayFilter() -> rsock{};\n'.format(index, i, index*10+i, i) + + # rstr += '\n' + # for index in range(4): + # if (index < num_interfaces): + # for i in range(0,3): + # if (i < num_interfaces): + # rstr += 'of{}[{}] -> [{}]of{};\n'.format(index*10+i, 1, 1 , index*10+i) + # rstr += 'of{}[{}] -> Discard; \n of{}[{}] -> Discard; \n'.format(index*10+i, 2, index*10+i, 3) + + - #(iface_name, ipaddr, macaddr) = self.interfaces[0] - #rstr += '\nSocket("UDP", {}, 8769, SNAPLEN 65536) -> [4]{}\n'.format( + # rstr += '\n' + # (iface_name, ipaddr, macaddr) = self.interfaces[0] + # rstr += '\nSocket("UDP", {}, 8769, SNAPLEN 65536) -> [4]{}\n'.format( # ipaddr, self.name) rstr += '\nControlSocket(tcp, 7777);\n' return rstr diff --git a/tools/overlay/xiaclientconfigurator.py b/tools/overlay/xiaclientconfigurator.py new file mode 100644 index 000000000..09e5aae55 --- /dev/null +++ b/tools/overlay/xiaclientconfigurator.py @@ -0,0 +1,162 @@ +import os +import sys + +from twisted.internet import reactor +from twisted.internet import defer +from twisted.internet.protocol import Protocol, ClientFactory +from twisted.protocols.basic import Int32StringReceiver +from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol + +# Bring in xia and overlay tools into path +srcdir = os.getcwd()[:os.getcwd().rindex('xia-core')+len('xia-core')] +sys.path.append(os.path.join(srcdir, 'bin')) +sys.path.append(os.path.join(srcdir, 'tools/overlay')) + +import xiapyutils +import clientconfig_pb2 + +from ConfigParser import RawConfigParser + +mobility_time = 5 + +class XIAClientConfigReader: + def __init__(self, config_filename): + self.routers = {} + self.default_router = {} + self.control_addr = {} + self.control_port = {} + self.aid = {} + self.ad = {} + self.hid = {} + self.router_addr = {} + self.router_iface = {} + self.serverdag = {} + self.mobile = {} + + # Read in the config file + parser = RawConfigParser() + parser.read(config_filename) + + # Router names are the section names in the config file + clients = parser.sections() + if len(clients) == 0: + print "ERROR: No sections found in config file" + + # Read in info into our internal data structures + for client in clients: + + # Interface names for each router (comma separated list) + routers = parser.get(client, 'Routers') + routers = routers.replace(' ', '') + router_list = routers.split(',') + self.routers[client] = router_list + + iface = parser.get(client, 'Interfaces') + iface = iface.replace(' ', '') + ifaces = iface.split(',') + self.router_iface[client] = {} + r_iface = {} + for i in range(len(ifaces)): + r_iface[router_list[i]] = ifaces[i] + self.router_iface[client] = r_iface + + self.default_router[client] = parser.get(client, 'Default') + self.control_addr[client] = parser.get(client, 'ControlAddress') + self.control_port[client] = parser.get(client, 'ControlPort') + self.serverdag[client] = parser.get(client, 'ServerDag') + self.aid[client] = parser.get(client, 'AID') + self.mobile[client] = False + try: + if parser.getboolean(client, "Mobile"): + self.mobile[client] = True + except: + pass + + def clients(self): + return self.routers.keys() + +class ConfigClient(Int32StringReceiver): + def __init__(self, client, clientConfigurator): + self.client = client + self.clientConfigurator = clientConfigurator + self.connected_clients = 0 + + def connectionLost(self, reason): + #self.connected_clients.remove(self) + print "Lost connection with " + self.client + self.connected_clients -= 1 + if self.clientConfigurator.connected_clients == 0: + print "!!!!!!!!!!! Stopping the configurator !!!!!!!!!!!!!" + #reactor.stop() + + def connectionMade(self): + # configure with default router + self.connected_clients += 1 + self.sendConfig(self.clientConfigurator.clientConfig.default_router[self.client]) + + if self.clientConfigurator.clientConfig.mobile[self.client] == True: + print "Making " + self.client + "mobile" + # We don't want to recursively do this, disable mobility + self.clientConfigurator.clientConfig.mobile[self.client] = False + for router in self.clientConfigurator.clientConfig.routers[self.client]: + print "\n Checking out router " + router + "\n" + if router != self.clientConfigurator.clientConfig.default_router[self.client]: + print "Adding a call for " + router + reactor.callLater(mobility_time, self.mobilityConfig, self.client, router) + + def sendConfig(self, router): + response = clientconfig_pb2.Config() + print "-----------------------------------" + print "Sending config to " + self.client + print "-----------------------------------" + response.name = self.client + response.ipaddr = self.clientConfigurator.clientConfig.router_addr[router] + response.iface = self.clientConfigurator.clientConfig.router_iface[self.client][router] + response.port = "8770" + response.AID = self.clientConfigurator.clientConfig.aid[self.client] + response.AD = self.clientConfigurator.clientConfig.ad[router] + response.HID =self.clientConfigurator.clientConfig.hid[router] + response.serverdag = self.clientConfigurator.clientConfig.serverdag[self.client] + + self.sendString(response.SerializeToString()) + print response.SerializeToString() + print "-----------------------------------" + + + def mobilityConfig(self, client, router): + # new default router + self.clientConfigurator.clientConfig.default_router[client] = router + endpoint = TCP4ClientEndpoint(reactor, self.clientConfigurator.clientConfig.control_addr[client], + int(self.clientConfigurator.clientConfig.control_port[client])) + + d = connectProtocol(endpoint, ConfigClient(client, self.clientConfigurator)) + + +class XIAClientConfigurator(): + def __init__(self, configurator): + self.connected_clients = 0 + + clientConfig = XIAClientConfigReader('tools/overlay/client.conf') + for client in clientConfig.clients(): + print client + ':' + for router in clientConfig.routers[client]: + clientConfig.ad[router] = configurator.xids[router][0] + clientConfig.hid[router] = configurator.xids[router][1] + clientConfig.router_addr[router] = configurator.config.host_ipaddrs[router] + print configurator.xids[router] + + self.clientConfig = clientConfig + + def configureClient(self): + for client in self.clientConfig.clients(): + endpoint = TCP4ClientEndpoint(reactor, + self.clientConfig.control_addr[client], + int(self.clientConfig.control_port[client])) + + d = connectProtocol(endpoint, ConfigClient(client, self)) + #d.addCallback(self.addClient) + + #reactor.run() + + def addClient(self): + self.connected_clients += 1 diff --git a/tools/overlay/xiaconfighelper.py b/tools/overlay/xiaconfighelper.py index 8b6fd8176..510fc98a3 100644 --- a/tools/overlay/xiaconfighelper.py +++ b/tools/overlay/xiaconfighelper.py @@ -2,6 +2,7 @@ import os import sys import subprocess +import inspect # Install python-twisted package for this functionality from twisted.internet.protocol import Protocol, Factory @@ -34,13 +35,11 @@ def __init__(self, common_data, addr): def connectionMade(self): self.sendString(xiaconfigdefs.HELPER_GREETING); - def connectionLost(self, reason): + def connectionLost(self, reason): # Clean up any state created in common_data for this connection print "Connection to client lost" def handleInterfaceRequest(self, request): - print "Got interface request" - # Fill in interface information for if_info in request.ifrequest.interfaces: if_info.ipaddr = interfaces.get_ip_addr(if_info.name) @@ -170,7 +169,6 @@ def stringReceived(self, request): #self.transport.loseConnection(); class HelperFactory(Factory): - def __init__(self): self.common_data = {} diff --git a/tools/overlay/xiaconfigreader.py b/tools/overlay/xiaconfigreader.py index ebcf8cf09..ca560d53b 100644 --- a/tools/overlay/xiaconfigreader.py +++ b/tools/overlay/xiaconfigreader.py @@ -1,14 +1,17 @@ from ConfigParser import RawConfigParser +import genkeys class XIAConfigReader: def __init__(self, config_filename): self.control_addrs = {} # router: ctrl_addr self.router_ifaces = {} # router: [iface1,...] self.host_ifaces = {} # router: host_iface + self.host_ipaddrs = {} # router: host ipaddr # todo fill this self.route_info = {} # router: (dest,our_iface,their_iface,their_name) self.xcache = {} # router: runs_xcache self.nameserver = "" - + self.sid = {} # router : routing sid + # Read in the config file parser = RawConfigParser() parser.read(config_filename) @@ -27,6 +30,12 @@ def __init__(self, config_filename): # AID host interface for each router self.host_ifaces[router] = parser.get(router, 'HostInterface') + # IP Address of host iface + self.host_ipaddrs[router] = parser.get(router, 'HostAddr') + + # Routing SID + self.sid[router] = genkeys.create_new_SID() + # Check if this is a nameserver try: if parser.getboolean(router, "NameServer"): diff --git a/tools/overlay/xiaconfigurator.py b/tools/overlay/xiaconfigurator.py index ddf648108..92558d193 100644 --- a/tools/overlay/xiaconfigurator.py +++ b/tools/overlay/xiaconfigurator.py @@ -19,6 +19,7 @@ # Bring in xia and overlay tools into path srcdir = os.getcwd()[:os.getcwd().rindex('xia-core')+len('xia-core')] + sys.path.append(os.path.join(srcdir, 'bin')) sys.path.append(os.path.join(srcdir, 'tools/overlay')) @@ -26,12 +27,17 @@ import xiaconfigdefs import configrequest_pb2 +import clientconfig_pb2 from xiaconfigreader import XIAConfigReader +from xiaclientconfigurator import XIAClientConfigurator from routerclick import RouterClick -class ConfigClient(Int32StringReceiver): +import inspect + +class ConfigRouter(Int32StringReceiver): def __init__(self, router, configurator, xid_wait): + self.router = router self.configurator = configurator self.initialized = False @@ -40,8 +46,12 @@ def __init__(self, router, configurator, xid_wait): def connectionLost(self, reason): self.configurator.protocol_instances.remove(self) if len(self.configurator.protocol_instances) == 0: - reactor.stop() - + print "Going to configure clients now" + # configure client after last router is configured + clientConfigurator = XIAClientConfigurator(self.configurator) + clientConfigurator.configureClient() + #reactor.stop() + def stringReceived(self, data): if not self.initialized: # Get greeting from server and send a request for interfaces @@ -160,6 +170,8 @@ def sendIPRoutesRequest(self): # Destination router, our interface, nexthop iface, nexthop name dest, our_iface, next_iface, next_name = route + print("Adding route : ") + print(route) # Convert dest router name to corresponding AD dest_ad, dest_hid = self.configurator.xids[dest] @@ -176,6 +188,11 @@ def sendIPRoutesRequest(self): route = "./bin/xroute -a AD,{},{},{}:{}".format( dest_ad, port, ipaddr, next_port) request.routes.route_cmds.append(route) + dest_sid = self.configurator.config.sid[dest] + sid_route = "./bin/xroute -a SID,{},{},{}:{},{}".format( + dest_sid, port, ipaddr, 8772, 7) + print("Sending %s" %sid_route) + request.routes.route_cmds.append(sid_route) self.sendString(request.SerializeToString()) def handleIPRoutesResponse(self, response): @@ -211,6 +228,7 @@ def handleStartXcacheResponse(self, response): self.transport.loseConnection() def handleGatherXIDsResponse(self, response): + if response.type != configrequest_pb2.Request.GATHER_XIDS: print "ERROR: Invalid gather XIDs response" self.transport.loseConnection() @@ -220,6 +238,7 @@ def handleGatherXIDsResponse(self, response): self.configurator.xids[self.router] = (ad, hid) self.xid_wait.callback(self) + class XIAConfigurator: def __init__(self, config): self.config = config @@ -228,6 +247,8 @@ def __init__(self, config): self.resolvconf = "" self.xids = {} # router: (ad, hid) self.iface_addrs = {} # (router, iface_name) : ipaddr + self.connected_clients = [] + print self.nameserver, 'is the nameserver' print 'Here are the routers we know of' @@ -238,6 +259,7 @@ def __init__(self, config): # All routers sent in their AD, HID. Send IP routes to all routers def sendIPRoutes(self, result): + for (success, protocol) in result: if success: print "Sending IP routes to {}".format(protocol.router) @@ -246,13 +268,16 @@ def sendIPRoutes(self, result): print "ERROR: failure sending IP routes for a protocol" def gotProtocol(self, protocol): + self.protocol_instances.append(protocol) def configure(self): + xid_waiters = [] for router in self.config.routers(): # Endpoint for client connection + endpoint = TCP4ClientEndpoint(reactor, self.config.control_addr(router), xiaconfigdefs.HELPER_PORT) @@ -261,8 +286,8 @@ def configure(self): xid_wait = defer.Deferred() xid_waiters.append(xid_wait) - # Link ConfigClient protocol instance to endpoint - d = connectProtocol(endpoint, ConfigClient(router, self, xid_wait)) + # Link ConfigRouter protocol instance to endpoint + d = connectProtocol(endpoint, ConfigRouter(router, self, xid_wait)) d.addCallback(self.gotProtocol) # Callback called, when all routers have collected their XIDs @@ -271,6 +296,7 @@ def configure(self): reactor.run() + if __name__ == "__main__": conf_file = os.path.join(xiapyutils.xia_srcdir(), 'tools/overlay/demo.conf') config = XIAConfigReader(conf_file)