Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic BIER elements #397

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions DISTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ archive.hh
args.hh
array_memory.hh
atomic.hh
biertable.hh
bighashmap.cc
bighashmap.hh
bighashmap_arena.hh
Expand Down Expand Up @@ -474,6 +475,7 @@ storage.hh
threadsched.hh

./include/clicknet:
bier.h
dhcp.h
ether.h
fddi.h
Expand All @@ -493,6 +495,7 @@ wifi.h
archive.cc
args.cc
atomic.cc
biertable.cc
bighashmap_arena.cc
bitvector.cc
clp.c
Expand Down
6 changes: 6 additions & 0 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ fi])
ELEMENTS_ARG_ENABLE(analysis, [include elements for network analysis], yes)
ELEMENTS_ARG_ENABLE(app, [include application-level elements], yes)
ELEMENTS_ARG_ENABLE(aqm, [include active queue management elements], yes)
ELEMENTS_ARG_ENABLE(bier, [include BIER elements], NO)
ELEMENTS_ARG_ENABLE(ethernet, [include Ethernet elements], yes)
ELEMENTS_ARG_ENABLE(etherswitch, [include Ethernet switch elements], NO)
ELEMENTS_ARG_ENABLE(flow, [include Enable flow system and elements], NO, enable_flow=yes, [ -a "x$enable_batch" = xyes ] )
Expand Down Expand Up @@ -1082,6 +1083,11 @@ if test "x$enable_ip6" = xyes; then
EXTRA_DRIVER_OBJS="ip6address.o ip6flowid.o ip6table.o $EXTRA_DRIVER_OBJS"
EXTRA_TOOL_OBJS="ip6address.o $EXTRA_TOOL_OBJS"
fi

if test "x$enable_bier" = xyes; then
EXTRA_DRIVER_OBJS="biertable.o $EXTRA_DRIVER_OBJS"
fi

AC_SUBST(EXTRA_DRIVER_OBJS)
AC_SUBST(EXTRA_TOOL_OBJS)

Expand Down
106 changes: 106 additions & 0 deletions elements/bier/bierroutetable.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* bierroutetable.{cc,hh} -- implement handlers for BIFT element
* Nicolas Rybowski
*
* Copyright (c) 2024 UCLouvain
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/

#include <click/config.h>
#include "bierroutetable.hh"
#include <click/args.hh>
#include <click/error.hh>
#include <click/glue.hh>
#include <click/ip6address.hh>
#include <click/ipaddress.hh>
CLICK_DECLS

void* BierRouteTable::cast(const char *name) {
if (strcmp(name, "BierRouteTable") == 0)
return (void*) this;
else
return Element::cast(name);
}

int BierRouteTable::add_route(bfrid, IP6Address, bitstring, IP6Address, int, String, ErrorHandler *errh) {
return errh->error("cannot add routes to this routing table");
}

int BierRouteTable::del_route(bfrid, ErrorHandler *errh) {
return errh->error("cannot del routes to this routing table");
}

String BierRouteTable::dump_routes() {
return String();
}

int BierRouteTable::add_route_handler(const String &conf, Element *e, void *, ErrorHandler *errh) {
BierRouteTable *r = static_cast<BierRouteTable *>(e);
Vector<String> words;
cp_spacevec(conf, words);

bitstring fbm;
IP6Address nxt;
int output;
String ifname;
String raw_bfrs;

if (
Args(words, r, errh)
.read_mp("BITSTRING", fbm)
.read_mp("NXT", nxt)
.read_mp("IFIDX", output)
.read_mp("IFNAME", ifname)
.read_mp("BFR", raw_bfrs)
.complete() < 0
)
return -1;

Vector<String> bfrs;
cp_argvec(raw_bfrs, bfrs);

for (int i=0; i<bfrs.size(); i++) {
Vector<String> bfr = bfrs[i].split('_');
if (bfr.size() != 2) {
click_chatter("Invalid BFR specification. Should be \"BFR <bfr-id>_<bfr-prefix>\"");
continue;
}
if (r->add_route((bfrid) atoi(bfr[0].c_str()), IP6Address(bfr[1]), fbm, nxt, output, ifname, errh)) {
click_chatter("Failed to add BIFT entry. Ignoring.");
continue;
}
}

return 0;
}

String BierRouteTable::table_handler(Element *e, void *) {
BierRouteTable *r = static_cast<BierRouteTable *>(e);
return r->dump_routes();
}

int BierRouteTable::del_route_handler(const String &conf, Element *e, void *, ErrorHandler *errh) {
BierRouteTable *r = static_cast<BierRouteTable *>(e);
Vector<String> words;
cp_spacevec(conf, words);

bfrid bfrid;

if (Args(words, r, errh).read_mp("BFR-ID", bfrid).complete() < 0)
return -1;

return r->del_route(bfrid, errh);

}

CLICK_ENDDECLS
ELEMENT_PROVIDES(BierRouteTable)
27 changes: 27 additions & 0 deletions elements/bier/bierroutetable.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef CLICK_BIERROUTETABLE_HH
#define CLICK_BIERROUTETABLE_HH
#include <click/glue.hh>
#include <click/batchelement.hh>
#include <click/ip6address.hh>
#include <clicknet/bier.h>
CLICK_DECLS

class BierRouteTable : public BatchElement {
public:
void* cast(const char*) override;
const char *port_count() const override { return PORTS_0_0; }

virtual int add_route(bfrid, IP6Address, bitstring, IP6Address, int, String, ErrorHandler*);
virtual int del_route(bfrid, ErrorHandler*);
virtual String dump_routes();

static int add_route_handler(const String&, Element*, void*, ErrorHandler*);
static int del_route_handler(const String&, Element*, void*, ErrorHandler*);
static String table_handler(Element*, void*);

private:
uint16_t _bfr_id;
};

CLICK_ENDDECLS
#endif
100 changes: 100 additions & 0 deletions elements/bier/checkbierheader.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* checkbierheader.{cc,hh} -- checks BIER header for correctness
* Nicolas Rybowski
*
* Copyright (c) 2024 UCLouvain
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/

#include <click/config.h>
#include "checkbierheader.hh"
#include <click/element.hh>
#include <clicknet/ip6.h>
#include <click/packet.hh>
#include <clicknet/bier.h>
#include <click/args.hh>
#include <click/error.hh>
#include <click/standard/alignmentinfo.hh>

CLICK_DECLS

CheckBIERHeader::CheckBIERHeader() : _offset(0) {
_drops = 0;
}

CheckBIERHeader::~CheckBIERHeader() {}

int CheckBIERHeader::configure(Vector<String> &conf,ErrorHandler *errh) {
if (Args(conf, this, errh)
.read_p("OFFSET", _offset)
.complete() < 0
)
return -1;
return 0;
}

void CheckBIERHeader::drop(Packet *p) {
if (_drops == 0) {
click_chatter("BIER header check failed");
}
_drops++;

if (noutputs() == 2) {
output(1).push(p);
} else {
p->kill();
}

}

Packet *CheckBIERHeader::simple_action(Packet *p) {
const click_bier *bier;
unsigned plen;

bier = reinterpret_cast<const click_bier*>(p->data());
plen = p->length();

if((int)plen < (int)sizeof(click_bier)) {
click_chatter("BIERin6 header too small");
goto drop;
}

// TODO: check that BSL is different from 0

// TODO: check that BS is not NULL

return(p);

drop:
drop(p);
return 0;
}

String CheckBIERHeader::read_handler(Element *e, void *thunk) {
CheckBIERHeader *c = reinterpret_cast<CheckBIERHeader *>(e);
switch (reinterpret_cast<uintptr_t>(thunk)) {
case h_drops: {
return String(c->_drops);
}
defaut: {
return String();
}
}
}

void CheckBIERHeader::add_handlers() {
add_read_handler("drops", read_handler, h_drops);
}

CLICK_ENDDECLS
EXPORT_ELEMENT(CheckBIERHeader)
ELEMENT_MT_SAFE(CheckBIERHeader)
58 changes: 58 additions & 0 deletions elements/bier/checkbierheader.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef CLICK_CHECKBIERHEADER_HH
#define CLICK_CHECKBIERHEADER_HH
#include <click/batchelement.hh>
#include <click/confparse.hh>
#include <clicknet/bier.h>
CLICK_DECLS

/*
* =c
* CheckBIERHeader([OFFSET])
* =s bier
*
* =d
*
* Expects BIER packets as input starting at OFFSET bytes. Default OFFSET is zero.
* Checks that thet packet's length is reasonable.
* Pushes invalid or non BIER packets out on output 1, unless output 1 was unused; if so,
* drop the packets.
*
* Keyword arguments are:
*
* =over 8
*
* =item OFFSET
*
* Unsigned integer. Byte position at which the BIER header begins. Default is 0.
*
* =back
*
*/

class CheckBIERHeader : public SimpleElement<CheckBIERHeader> {
public:
CheckBIERHeader();
~CheckBIERHeader();

const char *class_name() const override { return "CheckBIERHeader"; }
const char *port_count() const override { return PORTS_1_1X2; }
const char *processing() const override { return PROCESSING_A_AH; }

int configure(Vector<String> &, ErrorHandler *) CLICK_COLD;
void add_handlers() CLICK_COLD;

Packet *simple_action(Packet *p);

private:
int _offset;
atomic_uint64_t _drops;

enum {h_drops};

void drop(Packet *p);
static String read_handler(Element *e, void *thunk) CLICK_COLD;

};

CLICK_ENDDECLS
#endif
Loading