Commit 9a5ef043 authored by Jan Maria Matejka's avatar Jan Maria Matejka
Browse files

Merge branch 'mq-custom' into int-new

parents 0e492063 265419a3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include "lib/resource.h"
#include "lib/timer.h"


/* Configuration structure */

struct config {
@@ -128,9 +127,12 @@ struct sym_scope {
#define SYM_FUNCTION 3
#define SYM_FILTER 4
#define SYM_TABLE 5
#define SYM_ATTRIBUTE 6

#define SYM_VARIABLE 0x100	/* 0x100-0x1ff are variable types */
#define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
#define SYM_CONSTANT 0x200	/* 0x200-0x2ff are variable types */
#define SYM_CONSTANT_RANGE SYM_CONSTANT ... (SYM_CONSTANT | 0xff)

#define SYM_TYPE(s) (((struct f_val *) (s)->def)->type)
#define SYM_VAL(s) (((struct f_val *) (s)->def)->val)
+7 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ configuration - something in config which is not keyword.
Ondrej Filip <it/&lt;feela@network.cz&gt;/,
Pavel Machek <it/&lt;pavel@ucw.cz&gt;/,
Martin Mares <it/&lt;mj@ucw.cz&gt;/,
Jan Matejka <it/&lt;mq@jmq.cz&gt;/,
Maria Jan Matejka <it/&lt;mq@jmq.cz&gt;/,
Ondrej Zajicek <it/&lt;santiago@crfreenet.org&gt;/
</author>

@@ -552,6 +552,12 @@ include "tablename.conf";;
	constants based on /etc/iproute2/rt_* files. A list of defined constants
	can be seen (together with other symbols) using 'show symbols' command.

	<tag><label id="opt-attribute">attribute <m/type/ <m/name/</tag>
	Define a custom route attribute. You can set and get it in filters like
	any other route atribute. This feature is intended for marking routes
	in import filters for export filtering purposes instead of locally
	assigned BGP communities which have to be deleted in export filters.

	<tag><label id="opt-router-id">router id <m/IPv4 address/</tag>
	Set BIRD's router ID. It's a world-wide unique identification of your
	router, usually one of router's IPv4 addresses. Default: the lowest
+30 −13
Original line number Diff line number Diff line
@@ -417,7 +417,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
	ADD, DELETE, CONTAINS, RESET,
	PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
	EMPTY,
	FILTER, WHERE, EVAL,
	FILTER, WHERE, EVAL, ATTRIBUTE,
	BT_ASSERT, BT_TEST_SUITE, FORMAT)

%nonassoc THEN
@@ -455,6 +455,11 @@ filter_eval:
   EVAL term { f_eval_int($2); }
 ;

conf: custom_attr ;
custom_attr: ATTRIBUTE type SYM ';' {
  cf_define_symbol($3, SYM_ATTRIBUTE, ca_lookup(new_config->pool, $3->name, $2)->fda);
};

conf: bt_test_suite ;
bt_test_suite:
 BT_TEST_SUITE '(' SYM ',' text ')' {
@@ -834,14 +839,22 @@ function_call:

symbol:
   SYM {
     switch ($1->class & 0xff00) {
       case SYM_CONSTANT: $$ = f_new_inst(FI_CONSTANT_INDIRECT); break;
       case SYM_VARIABLE: $$ = f_new_inst(FI_VARIABLE); break;
       default: cf_error("%s: variable expected.", $1->name);
     }

     switch ($1->class & 0xffff) {
       case SYM_CONSTANT_RANGE:
         $$ = f_new_inst(FI_CONSTANT_INDIRECT);
	 goto cv_common;
       case SYM_VARIABLE_RANGE:
         $$ = f_new_inst(FI_VARIABLE);
       cv_common:
         $$->a1.p = $1->def;
         $$->a2.p = $1->name;
	 break;
       case SYM_ATTRIBUTE:
         $$ = f_new_inst_da(FI_EA_GET, *((struct f_dynamic_attr *) $1->def));
	 break;
       default:
         cf_error("%s: variable expected.", $1->name);
     }
   }

static_attr:
@@ -1001,11 +1014,15 @@ cmd:
   }
 | SYM '=' term ';' {
     DBG( "Ook, we'll set value\n" );
     if (($1->class & ~T_MASK) != SYM_VARIABLE)
       cf_error( "You may set only variables." );
     if ($1->class == SYM_ATTRIBUTE) {
       $$ = f_new_inst_da(FI_EA_SET, *((struct f_dynamic_attr *) $1->def));
       $$->a1.p = $3;
     } else if (($1->class & ~T_MASK) == SYM_VARIABLE) {
       $$ = f_new_inst(FI_SET);
       $$->a1.p = $1;
       $$->a2.p = $3;
     } else
       cf_error( "Symbol `%s' is read-only.", $1->name );
   }
 | RETURN term ';' {
     DBG( "Ook, we'll return the value\n" );
+144 −0
Original line number Diff line number Diff line
@@ -10,6 +10,9 @@
#include "nest/bird.h"
#include "conf/conf.h"
#include "filter/filter.h"
#include "lib/idm.h"
#include "nest/protocol.h"
#include "nest/route.h"

#define P(a,b) ((a<<8) | b)

@@ -105,3 +108,144 @@ filter_name(struct filter *filter)
  else
    return filter->name;
}

#define CA_KEY(n)	n->name, n->fda.type
#define CA_NEXT(n)	n->next
#define CA_EQ(na,ta,nb,tb)	(!strcmp(na,nb) && (ta == tb))
#define CA_FN(n,t)	(mem_hash(n, strlen(n)) ^ (t*0xaae99453U))
#define CA_ORDER	8 /* Fixed */

struct ca_storage {
  struct ca_storage *next;
  struct f_dynamic_attr fda;
  u32 uc;
  char name[0];
};

HASH(struct ca_storage) ca_hash;

static struct idm ca_idm;
static struct ca_storage **ca_storage;
static uint ca_storage_max;

static void
ca_free(resource *r)
{
  struct custom_attribute *ca = (void *) r;
  struct ca_storage *cas = HASH_FIND(ca_hash, CA, ca->name, ca->fda->type);
  ASSERT(cas);

  ca->name = NULL;
  ca->fda = NULL;
  if (!--cas->uc) {
    uint id = EA_CUSTOM_ID(cas->fda.ea_code);
    idm_free(&ca_idm, id);
    HASH_REMOVE(ca_hash, CA, cas);
    ca_storage[id] = NULL;
    mb_free(cas);
  }
}

static void
ca_dump(resource *r)
{
  struct custom_attribute *ca = (void *) r;
  debug("name \"%s\" id 0x%04x ea_type 0x%02x f_type 0x%02x\n",
      ca->name, ca->fda->ea_code, ca->fda->type, ca->fda->f_type);
}

static struct resclass ca_class = {
  .name = "Custom attribute",
  .size = sizeof(struct custom_attribute),
  .free = ca_free,
  .dump = ca_dump,
  .lookup = NULL,
  .memsize = NULL,
};

struct custom_attribute *
ca_lookup(pool *p, const char *name, int f_type)
{
  int ea_type;

  switch (f_type) {
    case T_INT:
      ea_type = EAF_TYPE_INT;
      break;
    case T_IP:
      ea_type = EAF_TYPE_IP_ADDRESS;
      break;
    case T_QUAD:
      ea_type = EAF_TYPE_ROUTER_ID;
      break;
    case T_PATH:
      ea_type = EAF_TYPE_AS_PATH;
      break;
    case T_CLIST:
      ea_type = EAF_TYPE_INT_SET;
      break;
    case T_ECLIST:
      ea_type = EAF_TYPE_EC_SET;
      break;
    case T_LCLIST:
      ea_type = EAF_TYPE_LC_SET;
      break;
    default:
      cf_error("Custom route attribute of unsupported type");
  }

  static int inited = 0;
  if (!inited) {
    idm_init(&ca_idm, &root_pool, 8);
    HASH_INIT(ca_hash, &root_pool, CA_ORDER);

    ca_storage_max = 256;
    ca_storage = mb_allocz(&root_pool, sizeof(struct ca_storage *) * ca_storage_max);

    inited++;
  }

  struct ca_storage *cas = HASH_FIND(ca_hash, CA, name, ea_type);
  if (cas) {
    cas->uc++;
  } else {

    uint id = idm_alloc(&ca_idm);

    if (id >= EA_CUSTOM_BIT)
      cf_error("Too many custom attributes.");

    if (id >= ca_storage_max) {
      ca_storage_max *= 2;
      ca_storage = mb_realloc(ca_storage, sizeof(struct ca_storage *) * ca_storage_max * 2);
    }

    cas = mb_allocz(&root_pool, sizeof(struct ca_storage) + strlen(name) + 1);
    cas->fda = f_new_dynamic_attr(ea_type, f_type, EA_CUSTOM(id));
    cas->uc = 1;

    strcpy(cas->name, name);
    ca_storage[id] = cas;

    HASH_INSERT(ca_hash, CA, cas);
  }

  struct custom_attribute *ca = ralloc(p, &ca_class);
  ca->fda = &(cas->fda);
  ca->name = cas->name;
  return ca;
}

const char *
ea_custom_name(uint ea)
{
  uint id = EA_CUSTOM_ID(ea);
  if (id >= ca_storage_max)
    return NULL;

  if (!ca_storage[id])
    return NULL;

  return ca_storage[id]->name;
}
+1 −1
Original line number Diff line number Diff line
@@ -1063,7 +1063,7 @@ interpret(struct f_inst *what)
	break;
      }

      switch (what->aux & EAF_TYPE_MASK) {
      switch (e->type & EAF_TYPE_MASK) {
      case EAF_TYPE_INT:
	res.type = f_type;
	res.val.i = e->u.data;
Loading