Real broadcast mode for OSPFv2.

This commit is contained in:
Ondrej Zajicek 2012-05-14 11:47:41 +02:00
parent 0ec031f740
commit 95127cbbb7
9 changed files with 68 additions and 25 deletions

View file

@ -1825,6 +1825,7 @@ protocol ospf <name> {
type [broadcast|bcast|pointopoint|ptp| type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp]; nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast <switch>; strict nonbroadcast <switch>;
real broadcast <switch>;
check link <switch>; check link <switch>;
ecmp weight <num>; ecmp weight <num>;
authentication [none|simple|cryptographic]; authentication [none|simple|cryptographic];
@ -2058,6 +2059,16 @@ protocol ospf <name> {
If set, don't send hello to any undefined neighbor. This switch If set, don't send hello to any undefined neighbor. This switch
is ignored on other than NBMA or PtMP networks. Default value is no. is ignored on other than NBMA or PtMP networks. Default value is no.
<tag>real broadcast <m/switch/</tag>
In <cf/type broadcast/ or <cf/type ptp/ network
configuration, OSPF packets are sent as IP multicast
packets. This option changes the behavior to using
old-fashioned IP broadcast packets. This may be useful as a
workaround if IP multicast for some reason does not work or
does not work reliably. This is a non-standard option and
probably is not interoperable with other OSPF
implementations. Default value is no.
<tag>check link <M>switch</M></tag> <tag>check link <M>switch</M></tag>
If set, a hardware link state (reported by OS) is taken into If set, a hardware link state (reported by OS) is taken into
consideration. When a link disappears (e.g. an ethernet cable is consideration. When a link disappears (e.g. an ethernet cable is

View file

@ -130,7 +130,7 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL) CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY) CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE) CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
%type <t> opttext %type <t> opttext
%type <ld> lsadb_args %type <ld> lsadb_args
@ -287,6 +287,7 @@ ospf_iface_item:
| TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; } | TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
| TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; } | TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
| TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; } | TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
| REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); } | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); } | PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; } | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }

View file

@ -303,7 +303,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{ {
case OSPF_IT_BCAST: case OSPF_IT_BCAST:
case OSPF_IT_PTP: case OSPF_IT_PTP:
ospf_send_to(ifa, AllSPFRouters); ospf_send_to_all(ifa);
break; break;
case OSPF_IT_NBMA: case OSPF_IT_NBMA:

View file

@ -120,14 +120,25 @@ ospf_sk_open(struct ospf_iface *ifa)
sk->saddr = ifa->addr->ip; sk->saddr = ifa->addr->ip;
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)) if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
{ {
if (ifa->cf->real_bcast)
{
ifa->all_routers = ifa->addr->brd;
if (sk_set_broadcast(sk, 1) < 0)
goto err;
}
else
{
ifa->all_routers = AllSPFRouters;
sk->ttl = 1; /* Hack, this will affect just multicast packets */ sk->ttl = 1; /* Hack, this will affect just multicast packets */
if (sk_setup_multicast(sk) < 0) if (sk_setup_multicast(sk) < 0)
goto err; goto err;
if (sk_join_group(sk, AllSPFRouters) < 0) if (sk_join_group(sk, ifa->all_routers) < 0)
goto err; goto err;
} }
}
ifa->sk = sk; ifa->sk = sk;
ifa->sk_dr = 0; ifa->sk_dr = 0;
@ -265,7 +276,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s", OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
ifa->iface->name, ospf_is[oldstate], ospf_is[state]); ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
if ((ifa->type == OSPF_IT_BCAST) && ifa->sk) if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
{ {
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
ospf_sk_join_dr(ifa); ospf_sk_join_dr(ifa);
@ -536,6 +547,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
/* Check validity of interface type */ /* Check validity of interface type */
int old_type = ifa->type; int old_type = ifa->type;
u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
#ifdef OSPFv2 #ifdef OSPFv2
if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER)) if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
@ -545,10 +557,10 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
ifa->type = OSPF_IT_PTMP; ifa->type = OSPF_IT_PTMP;
#endif #endif
if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST)) if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_NBMA; ifa->type = OSPF_IT_NBMA;
if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST)) if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_PTMP; ifa->type = OSPF_IT_PTMP;
if (ifa->type != old_type) if (ifa->type != old_type)
@ -628,6 +640,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
if (ifa->stub != new_stub) if (ifa->stub != new_stub)
return 0; return 0;
if (new->real_bcast != ifa->cf->real_bcast)
return 0;
ifa->cf = new; ifa->cf = new;
ifa->marked = 0; ifa->marked = 0;
@ -1099,11 +1114,15 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
void void
ospf_iface_info(struct ospf_iface *ifa) ospf_iface_info(struct ospf_iface *ifa)
{ {
char *strict = ""; char *more = "";
if (ifa->strictnbma && if (ifa->strictnbma &&
((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))) ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
strict = "(strict)"; more = " (strict)";
if (ifa->cf->real_bcast &&
((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
more = " (real)";
if (ifa->type == OSPF_IT_VLINK) if (ifa->type == OSPF_IT_VLINK)
{ {
@ -1124,11 +1143,10 @@ ospf_iface_info(struct ospf_iface *ifa)
#else /* OSPFv3 */ #else /* OSPFv3 */
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id); cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
#endif #endif
cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict); cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
} }
cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state], cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
ifa->stub ? "(stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority); cli_msg(-1015, "\tPriority: %u", ifa->priority);
cli_msg(-1015, "\tCost: %u", ifa->cost); cli_msg(-1015, "\tCost: %u", ifa->cost);
if (ifa->oa->po->ecmp) if (ifa->oa->po->ecmp)

View file

@ -97,7 +97,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
if (ifa->type == OSPF_IT_BCAST) if (ifa->type == OSPF_IT_BCAST)
{ {
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
ospf_send_to(ifa, AllSPFRouters); ospf_send_to_all(ifa);
else if (ifa->cf->real_bcast)
ospf_send_to_bdr(ifa);
else else
ospf_send_to(ifa, AllDRouters); ospf_send_to(ifa, AllDRouters);
} }
@ -124,7 +126,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
if (ifa->type == OSPF_IT_BCAST) if (ifa->type == OSPF_IT_BCAST)
{ {
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
ospf_send_to(ifa, AllSPFRouters); ospf_send_to_all(ifa);
else if (ifa->cf->real_bcast)
ospf_send_to_bdr(ifa);
else else
ospf_send_to(ifa, AllDRouters); ospf_send_to(ifa, AllDRouters);
} }

View file

@ -314,7 +314,9 @@ ospf_lsupd_flood(struct proto_ospf *po,
{ {
case OSPF_IT_BCAST: case OSPF_IT_BCAST:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR)) if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to(ifa, AllSPFRouters); ospf_send_to_all(ifa);
else if (ifa->cf->real_bcast)
ospf_send_to_bdr(ifa);
else else
ospf_send_to(ifa, AllDRouters); ospf_send_to(ifa, AllDRouters);
break; break;
@ -327,7 +329,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
break; break;
case OSPF_IT_PTP: case OSPF_IT_PTP:
ospf_send_to(ifa, AllSPFRouters); ospf_send_to_all(ifa);
break; break;
case OSPF_IT_PTMP: case OSPF_IT_PTMP:

View file

@ -205,6 +205,7 @@ struct ospf_iface
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */ bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
#endif #endif
ip_addr all_routers; /* */
ip_addr drip; /* Designated router */ ip_addr drip; /* Designated router */
ip_addr bdrip; /* Backup DR */ ip_addr bdrip; /* Backup DR */
u32 drid; u32 drid;
@ -790,22 +791,23 @@ struct ospf_iface_patt
u32 deadc; u32 deadc;
u32 deadint; u32 deadint;
u32 inftransdelay; u32 inftransdelay;
u32 priority;
u32 strictnbma;
list nbma_list; list nbma_list;
u32 priority;
u32 voa; u32 voa;
u32 vid; u32 vid;
u16 rxbuf; u16 rxbuf;
u8 check_link;
u8 ecmp_weight;
#define OSPF_RXBUF_NORMAL 0 #define OSPF_RXBUF_NORMAL 0
#define OSPF_RXBUF_LARGE 1 #define OSPF_RXBUF_LARGE 1
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */ #define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
u32 autype; /* Not really used in OSPFv3 */ u16 autype; /* Not really used in OSPFv3 */
#define OSPF_AUTH_NONE 0 #define OSPF_AUTH_NONE 0
#define OSPF_AUTH_SIMPLE 1 #define OSPF_AUTH_SIMPLE 1
#define OSPF_AUTH_CRYPT 2 #define OSPF_AUTH_CRYPT 2
#define OSPF_AUTH_CRYPT_SIZE 16 #define OSPF_AUTH_CRYPT_SIZE 16
u8 strictnbma;
u8 check_link;
u8 ecmp_weight;
u8 real_bcast; /* Not really used in OSPFv3 */
#ifdef OSPFv2 #ifdef OSPFv2
list *passwords; list *passwords;

View file

@ -273,7 +273,7 @@ ospf_rx_hook(sock *sk, int size)
int src_local, dst_local UNUSED, dst_mcast; int src_local, dst_local UNUSED, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
dst_local = ipa_equal(sk->laddr, ifa->addr->ip); dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters); dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
#ifdef OSPFv2 #ifdef OSPFv2
/* First, we eliminate packets with strange address combinations. /* First, we eliminate packets with strange address combinations.
@ -287,6 +287,9 @@ ospf_rx_hook(sock *sk, int size)
if (!dst_mcast && !dst_local) if (!dst_mcast && !dst_local)
return 1; return 1;
/* Ignore my own broadcast packets */
if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
return 1;
#else /* OSPFv3 */ #else /* OSPFv3 */
/* In OSPFv3, src_local and dst_local mean link-local. /* In OSPFv3, src_local and dst_local mean link-local.

View file

@ -19,6 +19,8 @@ void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
void ospf_send_to_bdr(struct ospf_iface *ifa); void ospf_send_to_bdr(struct ospf_iface *ifa);
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip); void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; } static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
static inline unsigned static inline unsigned