CF_ENUM(T_ENUM_RTS, RTS_, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
-CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
+CF_ENUM(T_ENUM_RTD, RTD_, BLACKHOLE, UNREACHABLE, PROHIBIT)
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6)
- CF_ENUM(T_ENUM_MPLS_POLICY, MPLS_POLICY_, NONE, STATIC, PREFIX, AGGREGATE)
+ CF_ENUM(T_ENUM_MPLS_POLICY, MPLS_POLICY_, NONE, STATIC, PREFIX, AGGREGATE, VRF)
%type <i32> idval
%type <f> imexport
break;
case MPLS_POLICY_AGGREGATE:
- rta_free(fec->rta);
- HASH_REMOVE2(m->rta_hash, RTA, m->pool, fec);
+ ea_free(fec->rta->l);
+ HASH_REMOVE2(m->attrs_hash, RTA, m->pool, fec);
break;
+ case MPLS_POLICY_VRF:
+ ASSERT(m->vrf_fec == fec);
+ m->vrf_fec = NULL;
+ break;
+
default:
bug("Unknown fec type");
}
}
static void
-mpls_apply_fec(rte *r, struct mpls_fec *fec, linpool *lp)
+mpls_apply_fec(rte *r, struct mpls_fec *fec)
{
- struct ea_list *ea = lp_allocz(lp, sizeof(struct ea_list) + 2 * sizeof(eattr));
-
- rta *old_attrs = r->attrs;
-
- if (rta_is_cached(old_attrs))
- r->attrs = rta_do_cow(r->attrs, lp);
-
- *ea = (struct ea_list) {
- .next = r->attrs->eattrs,
- .flags = EALF_SORTED,
- .count = 2,
- };
-
- ea->attrs[0] = (struct eattr) {
- .id = EA_MPLS_LABEL,
- .type = EAF_TYPE_INT,
- .u.data = fec->label,
- };
-
- ea->attrs[1] = (struct eattr) {
- .id = EA_MPLS_POLICY,
- .type = EAF_TYPE_INT,
- .u.data = fec->policy,
- };
-
- r->attrs->eattrs = ea;
+ ea_set_attr_u32(&r->attrs, &ea_gen_mpls_label, 0, fec->label);
+ ea_set_attr_u32(&r->attrs, &ea_gen_mpls_policy, 0, fec->policy);
+
+ if (fec->policy == MPLS_POLICY_VRF)
+ {
- r->attrs->hostentry = NULL;
- r->attrs->dest = RTD_UNICAST;
- r->attrs->nh = (struct nexthop) { .iface = fec->iface };
- }
++ ea_unset_attr(&r->attrs, 0, &ea_gen_hostentry);
+
- if (rta_is_cached(old_attrs))
- {
- r->attrs = rta_lookup(r->attrs);
- rta_free(old_attrs);
++ struct nexthop_adata nhad = {
++ .nh.iface = fec->iface,
++ .ad.length = sizeof nhad - sizeof nhad.ad,
++ };
++ ea_set_attr_data(&r->attrs, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length);
+ }
}
mpls_damage_fec(m, fec);
break;
- case MPLS_POLICY_AGGREGATE:;
- uint class = ea_get_int(r->attrs->eattrs, EA_MPLS_CLASS, 0);
- fec = mpls_get_fec_by_rta(m, r->attrs, class);
+ case MPLS_POLICY_AGGREGATE:
+ fec = mpls_get_fec_by_destination(m, r->attrs);
break;
+ case MPLS_POLICY_VRF:
+ if (!m->vrf_iface)
+ return;
+
+ fec = mpls_get_fec_for_vrf(m);
+ break;
+
default:
log(L_WARN "Route %N has invalid MPLS policy %u", n, policy);
return;
struct mpls_fec *next_k; /* Next in mpls_fec.net_hash/rta_hash */
struct mpls_fec *next_l; /* Next in mpls_fec.label_hash */
union { /* Primary key */
- struct rta *rta;
+ struct ea_storage *rta;
+ struct iface *iface;
net_addr net[0];
};
};
pool *pool; /* Pool for FEC map */
slab *slabs[4]; /* Slabs for FEC allocation */
HASH(struct mpls_fec) net_hash; /* Hash table for MPLS_POLICY_PREFIX FECs */
- HASH(struct mpls_fec) rta_hash; /* Hash table for MPLS_POLICY_AGGREGATE FECs */
+ HASH(struct mpls_fec) attrs_hash; /* Hash table for MPLS_POLICY_AGGREGATE FECs */
HASH(struct mpls_fec) label_hash; /* Hash table for FEC lookup by label */
+ struct mpls_fec *vrf_fec; /* Single FEC for MPLS_POLICY_VRF */
struct channel *channel; /* MPLS channel for FEC announcement */
struct mpls_domain *domain; /* MPLS domain, keeping reference */
struct mpls_handle *handle; /* Handle for allocation of labels */
+ struct iface *vrf_iface;
u8 mpls_rts; /* Source value used for MPLS routes (RTS_*) */
- u8 mpls_scope; /* Scope value used for MPLS routes (SCOPE_*) */
};