zebra: add connected_check_ptp infrastructure

add a connected_check_ptp function which does the same as
connected_check, but takes an additional peer prefix argument.

also fix related prefixlen mixup in PtP addresses (the local part of a
PtP address always is /32, but previously the peer mask got copied.)

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2010-01-30 12:10:23 +01:00 committed by David Lamparter
parent 3df31ebb03
commit abffde07a3
3 changed files with 59 additions and 9 deletions

View file

@ -100,8 +100,10 @@ static void connected_announce(struct interface *ifp, struct connected *ifc)
}
/* If same interface address is already exist... */
struct connected *connected_check(struct interface *ifp, struct prefix *p)
struct connected *connected_check(struct interface *ifp,
union prefixconstptr pu)
{
const struct prefix *p = pu.p;
struct connected *ifc;
struct listnode *node;
@ -112,6 +114,33 @@ struct connected *connected_check(struct interface *ifp, struct prefix *p)
return NULL;
}
/* same, but with peer address */
struct connected *connected_check_ptp(struct interface *ifp,
union prefixconstptr pu,
union prefixconstptr du)
{
const struct prefix *p = pu.p;
const struct prefix *d = du.p;
struct connected *ifc;
struct listnode *node;
/* ignore broadcast addresses */
if (p->prefixlen != IPV4_MAX_PREFIXLEN)
d = NULL;
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
if (!prefix_same(ifc->address, p))
continue;
if (!CONNECTED_PEER(ifc) && !d)
return ifc;
if (CONNECTED_PEER(ifc) && d
&& prefix_same(ifc->destination, d))
return ifc;
}
return NULL;
}
/* Check if two ifc's describe the same address in the same state */
static int connected_same(struct connected *ifc1, struct connected *ifc2)
{
@ -145,7 +174,8 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
struct connected *current;
/* Check same connected route. */
if ((current = connected_check(ifp, (struct prefix *)ifc->address))) {
current = connected_check_ptp(ifp, ifc->address, ifc->destination);
if (current) {
if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
@ -238,7 +268,8 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
p = prefix_ipv4_new();
p->family = AF_INET;
p->prefix = *addr;
p->prefixlen = prefixlen;
p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
: prefixlen;
ifc->address = (struct prefix *)p;
/* If there is broadcast or peer address. */
@ -350,15 +381,25 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, u_char prefixlen,
struct in_addr *broad)
{
struct prefix_ipv4 p;
struct prefix_ipv4 p, d;
struct connected *ifc;
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefix = *addr;
p.prefixlen = prefixlen;
p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
: prefixlen;
if (broad) {
memset(&d, 0, sizeof(struct prefix_ipv4));
d.family = AF_INET;
d.prefix = *broad;
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, (struct prefix *)&p,
(struct prefix *)&d);
} else
ifc = connected_check_ptp(ifp, (struct prefix *)&p, NULL);
ifc = connected_check(ifp, (struct prefix *)&p);
if (!ifc)
return;

View file

@ -23,7 +23,10 @@
#define _ZEBRA_CONNECTED_H
extern struct connected *connected_check(struct interface *ifp,
struct prefix *p);
union prefixconstptr p);
extern struct connected *connected_check_ptp(struct interface *ifp,
union prefixconstptr p,
union prefixconstptr d);
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, u_char prefixlen,

View file

@ -242,7 +242,7 @@ int if_subnet_add(struct interface *ifp, struct connected *ifc)
/* Get address derived subnet node and associated address list, while
marking
address secondary attribute appropriately. */
cp = *ifc->address;
cp = *CONNECTED_PREFIX(ifc);
apply_mask(&cp);
rn = route_node_get(zebra_if->ipv4_subnets, &cp);
@ -267,12 +267,16 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc)
struct route_node *rn;
struct zebra_if *zebra_if;
struct list *addr_list;
struct prefix cp;
assert(ifp && ifp->info && ifc);
zebra_if = ifp->info;
cp = *CONNECTED_PREFIX(ifc);
apply_mask(&cp);
/* Get address derived subnet node. */
rn = route_node_lookup(zebra_if->ipv4_subnets, ifc->address);
rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
if (!(rn && rn->info)) {
zlog_warn(
"Trying to remove an address from an unknown subnet."
@ -966,6 +970,8 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected)
vty_out(vty,
(CONNECTED_PEER(connected) ? " peer " : " broadcast "));
prefix_vty_out(vty, connected->destination);
if (CONNECTED_PEER(connected))
vty_out(vty, "/%d", connected->destination->prefixlen);
}
if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))