/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memory/Allocator.h" #include "net/SwitchAdapter.h" #include "util/Identity.h" #include "wire/SwitchHeader.h" #include "util/Linker.h" Linker_require("net/SwitchAdapter.c") struct SwitchAdapter_pvt { struct SwitchAdapter pub; struct Log* log; Identity }; struct Header { struct SwitchHeader sh; uint32_t handle_be; }; #define Header_SIZE 16 Assert_compileTime(sizeof(struct Header) == Header_SIZE); static Iface_DEFUN incomingFromControlIf(struct Message* msg, struct Iface* controlIf) { struct SwitchAdapter_pvt* sa = Identity_containerOf(controlIf, struct SwitchAdapter_pvt, pub.controlIf); return Iface_next(&sa->pub.switchIf, msg); } static Iface_DEFUN incomingFromSessionManagerIf(struct Message* msg, struct Iface* sessionManagerIf) { struct SwitchAdapter_pvt* sa = Identity_containerOf(sessionManagerIf, struct SwitchAdapter_pvt, pub.sessionManagerIf); return Iface_next(&sa->pub.switchIf, msg); } static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* switchIf) { struct SwitchAdapter_pvt* sa = Identity_containerOf(switchIf, struct SwitchAdapter_pvt, pub.switchIf); if (msg->length < Header_SIZE) { Log_debug(sa->log, "DROP runt"); return 0; } Assert_true(!(((uintptr_t)msg->bytes) % 4) && "alignment"); struct Header* hdr = (struct Header*) msg->bytes; // The label comes in reversed from the switch because the switch doesn't know that we aren't // another switch ready to parse more bits, bit reversing the label yields the source address. // (the field is still big endian!) hdr->sh.label_be = Bits_bitReverse64(hdr->sh.label_be); if (hdr->handle_be == 0xffffffff) { return Iface_next(&sa->pub.controlIf, msg); } return Iface_next(&sa->pub.sessionManagerIf, msg); } struct SwitchAdapter* SwitchAdapter_new(struct Allocator* allocator, struct Log* log) { struct Allocator* alloc = Allocator_child(allocator); struct SwitchAdapter_pvt* out = Allocator_calloc(alloc, sizeof(struct SwitchAdapter_pvt), 1); out->pub.controlIf.send = incomingFromControlIf; out->pub.sessionManagerIf.send = incomingFromSessionManagerIf; out->pub.switchIf.send = incomingFromSwitchIf; out->log = log; Identity_set(out); return &out->pub; }