/* 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 .
*/
#ifndef EncodingScheme_H
#define EncodingScheme_H
#include "benc/String.h"
#include "benc/List.h"
#include "memory/Allocator.h"
#include "util/Linker.h"
Linker_require("switch/EncodingScheme.c");
#include
struct EncodingScheme_Form
{
// these only require 5 bits each but use 16 to avoid compiler injected padding
// which can screw up comparison by memcmp()
uint16_t bitCount;
uint16_t prefixLen;
uint32_t prefix;
};
struct EncodingScheme
{
struct EncodingScheme_Form* forms;
int count;
};
/**
* Get the number of the encoding form used to encode the first director in the given label.
* If there is no matching prefix for any of the forms then EncodingScheme_getFormNum_INVALID is
* returned.
*/
#define EncodingScheme_getFormNum_INVALID -1
int EncodingScheme_getFormNum(struct EncodingScheme* scheme, uint64_t routeLabel);
/**
* Convert the first director in a label from it's current form to the form given by convertTo.
* convertTo must be between zero and scheme->count unless you are asking for the cannonical form
* IE: the smallest possible represenation in which case convertTo should be:
* EncodingScheme_convertLabel_convertTo_CANNONICAL
*
* The return value will be the converted label unless conversion is not possible because the
* format of the label is invalid, the format of the label does not match the scheme, or the
* label cannot be converted without overrunning the acceptable label size in which case
* EncodingScheme_convertLabel_INVALID will be returned.
*/
#define EncodingScheme_convertLabel_convertTo_CANNONICAL (-5000)
#define EncodingScheme_convertLabel_INVALID (~((uint64_t)0))
uint64_t EncodingScheme_convertLabel(struct EncodingScheme* scheme,
uint64_t routeLabel,
int convertTo);
/**
* Check that the given encoding scheme is conformant to protocol.
* This will not check some things which are impossible to serialize (will never come from a
* working deserializer) such as unrepresentable bit-widths but it will check that a representable
* encoding scheme is indeed valid according to the protocol.
*/
bool EncodingScheme_isSane(struct EncodingScheme* scheme);
String* EncodingScheme_serialize(struct EncodingScheme* list,
struct Allocator* alloc);
struct EncodingScheme* EncodingScheme_deserialize(String* data,
struct Allocator* alloc);
struct EncodingScheme* EncodingScheme_defineFixedWidthScheme(int bitCount, struct Allocator* alloc);
struct EncodingScheme* EncodingScheme_defineDynWidthScheme(struct EncodingScheme_Form* forms,
int formCount,
struct Allocator* alloc);
#define EncodingScheme_clone(scheme, alloc) \
EncodingScheme_defineDynWidthScheme((scheme)->forms, (scheme)->count, (alloc))
static inline int EncodingScheme_formSize(const struct EncodingScheme_Form* form)
{
return form->bitCount + form->prefixLen;
}
int EncodingScheme_compare(struct EncodingScheme* a, struct EncodingScheme* b);
#define EncodingScheme_equals(a,b) (!EncodingScheme_compare(a,b))
struct EncodingScheme* EncodingScheme_fromList(List* scheme, struct Allocator* alloc);
List* EncodingScheme_asList(struct EncodingScheme* list, struct Allocator* alloc);
/**
* Return true if the route is to the switch's router interface.
*/
int EncodingScheme_isSelfRoute(struct EncodingScheme* scheme, uint64_t routeLabel);
/**
* @return non-zero if the route label is one hop.
*/
int EncodingScheme_isOneHop(struct EncodingScheme* scheme, uint64_t routeLabel);
#endif