diff options
-rw-r--r-- | proto/ospf/iface.c | 21 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 26 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 2 |
3 files changed, 48 insertions, 1 deletions
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index b30a811..83d591b 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -97,6 +97,27 @@ ospf_sk_open(struct ospf_iface *ifa) goto err; #endif + /* + * For OSPFv2: When sending a packet, it is important to have a + * proper source address. We expect that when we send one-hop + * unicast packets, OS chooses a source address according to the + * destination address (to be in the same prefix). We also expect + * that when we send multicast packets, OS uses the source address + * from sk->saddr registered to OS by sk_setup_multicast(). This + * behavior is needed to implement multiple virtual ifaces (struct + * ospf_iface) on one physical iface and is signalized by + * CONFIG_MC_PROPER_SRC. + * + * If this behavior is not available (for example on BSD), we create + * non-stub iface just for the primary IP address (see + * ospf_iface_stubby()) and we expect OS to use primary IP address + * as a source address for both unicast and multicast packets. + * + * FIXME: the primary IP address is currently just the + * lexicographically smallest address on an interface, it should be + * signalized by sysdep code which one is really the primary. + */ + sk->saddr = ifa->addr->ip; if (sk_setup_multicast(sk) < 0) goto err; diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index e824511..d345e49 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -42,6 +42,32 @@ * and deletion. Each LSA is kept in two pieces: header and body. Both of them are * kept in the endianity of the CPU. * + * In OSPFv2 specification, it is implied that there is one IP prefix + * for each physical network/interface (unless it is an ptp link). But + * in modern systems, there might be more independent IP prefixes + * associated with an interface. To handle this situation, we have + * one &ospf_iface for each active IP prefix (instead for each active + * iface); This behaves like virtual interface for the purpose of OSPF. + * If we receive packet, we associate it with a proper virtual interface + * mainly according to its source address. + * + * OSPF keeps one socket per &ospf_iface. This allows us (compared to + * one socket approach) to evade problems with a limit of multicast + * groups per socket and with sending multicast packets to appropriate + * interface in a portable way. The socket is associated with + * underlying physical iface and should not receive packets received + * on other ifaces (unfortunately, this is not true on + * BSD). Generally, one packet can be received by more sockets (for + * example, if there are more &ospf_iface on one physical iface), + * therefore we explicitly filter received packets according to + * src/dst IP address and received iface. + * + * Vlinks are implemented using particularly degenerate form of + * &ospf_iface, which has several exceptions: it does not have its + * iface or socket (it copies these from 'parent' &ospf_iface) and it + * is present in iface list even when down (it is not freed in + * ospf_iface_down()). + * * The heart beat of ospf is ospf_disp(). It is called at regular intervals * (&proto_ospf->tick). It is responsible for aging and flushing of LSAs in * the database, for routing table calculaction and it call area_disp() of every diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index ef51b9f..bb0b6af 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -159,7 +159,7 @@ struct ospf_iface { node n; struct iface *iface; /* Nest's iface */ - struct ifa *addr; + struct ifa *addr; /* IP prefix associated with that OSPF iface */ struct ospf_area *oa; struct object_lock *lock; sock *sk; /* IP socket (for DD ...) */ |