Split network destination structure from interface structure

This commit is contained in:
Jeremy Lakeman 2013-06-04 12:12:45 +09:30
parent d540c5d889
commit d47d1b1684
9 changed files with 93 additions and 83 deletions

View File

@ -228,7 +228,7 @@ unsigned char *_ob_append_space(struct __sourceloc __whence, struct overlay_buff
return r;
}
int _ob_append_bytes(struct __sourceloc __whence, struct overlay_buffer *b, unsigned char *bytes, int count)
int _ob_append_bytes(struct __sourceloc __whence, struct overlay_buffer *b, const unsigned char *bytes, int count)
{
if (_ob_makespace(__whence, b,count)) return WHY("ob_makespace() failed");
@ -263,7 +263,7 @@ int _ob_append_ui32(struct __sourceloc __whence, struct overlay_buffer *b, uint3
int _ob_append_ui64(struct __sourceloc __whence, struct overlay_buffer *b, uint64_t v)
{
if (ob_makespace(__whence, b, 8)) return WHY("ob_makespace() failed");
if (_ob_makespace(__whence, b, 8)) return WHY("ob_makespace() failed");
b->bytes[b->position] = (v >> 56) & 0xFF;
b->bytes[b->position+1] = (v >> 48) & 0xFF;
b->bytes[b->position+2] = (v >> 40) & 0xFF;

View File

@ -55,7 +55,7 @@ int _ob_makespace(struct __sourceloc whence, struct overlay_buffer *b,int bytes)
int ob_set(struct overlay_buffer *b, int ofs, unsigned char byte);
int _ob_append_byte(struct __sourceloc whence, struct overlay_buffer *b,unsigned char byte);
int _ob_append_bytes(struct __sourceloc whence, struct overlay_buffer *b,unsigned char *bytes,int count);
int _ob_append_bytes(struct __sourceloc whence, struct overlay_buffer *b,const unsigned char *bytes,int count);
int _ob_append_buffer(struct __sourceloc whence, struct overlay_buffer *b,struct overlay_buffer *s);
unsigned char *_ob_append_space(struct __sourceloc whence, struct overlay_buffer *b,int count);
int _ob_append_ui16(struct __sourceloc whence, struct overlay_buffer *b, uint16_t v);

View File

@ -65,7 +65,7 @@ static void
overlay_interface_close(overlay_interface *interface){
link_interface_down(interface);
enum_subscribers(NULL, mark_subscriber_down, interface);
INFOF("Interface %s addr %s is down", interface->name, inet_ntoa(interface->broadcast_address.sin_addr));
INFOF("Interface %s addr %s is down", interface->name, inet_ntoa(interface->destination.address.sin_addr));
unschedule(&interface->alarm);
unwatch(&interface->alarm);
close(interface->alarm.poll.fd);
@ -320,7 +320,7 @@ overlay_interface_init_socket(int interface_index)
const struct sockaddr *addr = (const struct sockaddr *)&interface->address;
interface->alarm.poll.fd = overlay_bind_socket(addr, sizeof(interface->broadcast_address), interface->name);
interface->alarm.poll.fd = overlay_bind_socket(addr, sizeof(interface->destination.address), interface->name);
if (interface->alarm.poll.fd<0){
interface->state=INTERFACE_STATE_DOWN;
return WHYF("Failed to bind interface %s", interface->name);
@ -328,8 +328,8 @@ overlay_interface_init_socket(int interface_index)
if (config.debug.packetrx || config.debug.io) {
char srctxt[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, (const void *)&interface->broadcast_address.sin_addr, srctxt, INET_ADDRSTRLEN))
DEBUGF("Bound to %s:%d", srctxt, ntohs(interface->broadcast_address.sin_port));
if (inet_ntop(AF_INET, (const void *)&interface->destination.address.sin_addr, srctxt, INET_ADDRSTRLEN))
DEBUGF("Bound to %s:%d", srctxt, ntohs(interface->destination.address.sin_port));
}
interface->alarm.poll.events=POLLIN;
@ -382,13 +382,14 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->prefer_unicast = ifconfig->prefer_unicast;
interface->default_route = ifconfig->default_route;
interface->socket_type = ifconfig->socket_type;
interface->encapsulation = ifconfig->encapsulation;
interface->destination.interface = interface;
interface->destination.encapsulation = ifconfig->encapsulation;
interface->uartbps = ifconfig->uartbps;
interface->ctsrts = ifconfig->ctsrts;
/* Pick a reasonable default MTU.
This will ultimately get tuned by the bandwidth and other properties of the interface */
interface->mtu=1200;
interface->destination.mtu=1200;
interface->state=INTERFACE_STATE_DOWN;
interface->alarm.poll.fd=0;
interface->debug = ifconfig->debug;
@ -446,11 +447,11 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
INFOF("Interface %s is running tickless", name);
if (tick_ms<0)
return WHYF("No tick interval %d specified for interface %s", interface->tick_ms, name);
return WHYF("No tick interval specified for interface %s", name);
interface->tick_ms = tick_ms;
interface->destination.tick_ms = tick_ms;
limit_init(&interface->transfer_limit, packet_interval);
limit_init(&interface->destination.transfer_limit, packet_interval);
interface->address.sin_family=AF_INET;
interface->address.sin_port = htons(ifconfig->port);
@ -458,9 +459,9 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->netmask=ifconfig->dummy_netmask;
interface->broadcast_address.sin_family=AF_INET;
interface->broadcast_address.sin_port = htons(ifconfig->port);
interface->broadcast_address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr;
interface->destination.address.sin_family=AF_INET;
interface->destination.address.sin_port = htons(ifconfig->port);
interface->destination.address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr;
interface->alarm.function = overlay_interface_poll;
interface_poll_stats.name="overlay_interface_poll";
@ -468,7 +469,7 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
if (ifconfig->socket_type==SOCK_DGRAM){
interface->address.sin_addr = src_addr;
interface->broadcast_address.sin_addr = broadcast;
interface->destination.address.sin_addr = broadcast;
interface->netmask = netmask;
interface->local_echo = 1;
@ -523,7 +524,9 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
directory_registration();
INFOF("Allowing a maximum of %d packets every %lldms", interface->transfer_limit.burst_size, interface->transfer_limit.burst_length);
INFOF("Allowing a maximum of %d packets every %lldms",
interface->destination.transfer_limit.burst_size,
interface->destination.transfer_limit.burst_length);
overlay_interface_count++;
return 0;
@ -600,7 +603,7 @@ static int should_drop(struct overlay_interface *interface, struct sockaddr_in a
if (memcmp(&addr, &interface->address, sizeof(addr))==0){
return interface->drop_unicasts;
}
if (memcmp(&addr, &interface->broadcast_address, sizeof(addr))==0){
if (memcmp(&addr, &interface->destination.address, sizeof(addr))==0){
if (interface->drop_broadcasts == 0)
return 0;
if (interface->drop_broadcasts >= 100)
@ -757,13 +760,13 @@ static void overlay_interface_poll(struct sched_ent *alarm)
alarm->alarm=-1;
time_ms_t now = gettime_ms();
if (interface->state==INTERFACE_STATE_UP && interface->tick_ms>0){
if (now >= interface->last_tx+interface->tick_ms)
if (interface->state==INTERFACE_STATE_UP && interface->destination.tick_ms>0){
if (now >= interface->destination.last_tx+interface->destination.tick_ms)
overlay_send_tick_packet(interface);
alarm->alarm=interface->last_tx+interface->tick_ms;
alarm->deadline=alarm->alarm+interface->tick_ms/2;
alarm->alarm=interface->destination.last_tx+interface->destination.tick_ms;
alarm->deadline=alarm->alarm+interface->destination.tick_ms/2;
}
switch(interface->socket_type){
case SOCK_DGRAM:
case SOCK_STREAM:
@ -817,7 +820,7 @@ overlay_broadcast_ensemble(overlay_interface *interface,
struct sockaddr_in *recipientaddr,
unsigned char *bytes,int len)
{
interface->last_tx = gettime_ms();
interface->destination.last_tx = gettime_ms();
if (config.debug.packettx)
{
@ -969,7 +972,7 @@ overlay_interface_register(char *name,
int broadcast_match = 0;
int name_match =0;
if (overlay_interfaces[i].broadcast_address.sin_addr.s_addr == broadcast.s_addr)
if (overlay_interfaces[i].destination.address.sin_addr.s_addr == broadcast.s_addr)
broadcast_match = 1;
name_match = !strcasecmp(overlay_interfaces[i].name, name);
@ -998,7 +1001,7 @@ overlay_interface_register(char *name,
if (found_interface>=0){
// try to reactivate the existing interface
overlay_interfaces[found_interface].address.sin_addr = addr;
overlay_interfaces[found_interface].broadcast_address.sin_addr = broadcast;
overlay_interfaces[found_interface].destination.address.sin_addr = broadcast;
overlay_interfaces[found_interface].netmask = mask;
return re_init_socket(found_interface);
}

View File

@ -999,7 +999,7 @@ void overlay_mdp_poll(struct sched_ent *alarm)
scans[i].interface = interface;
scans[i].current = ntohl(interface->address.sin_addr.s_addr & interface->netmask.s_addr)+1;
scans[i].last = ntohl(interface->broadcast_address.sin_addr.s_addr)-1;
scans[i].last = ntohl(interface->destination.address.sin_addr.s_addr)-1;
if (scans[i].last - scans[i].current>0x10000){
INFOF("Skipping scan on interface %s as the address space is too large",interface->name);
continue;

View File

@ -322,7 +322,7 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
}
/* Note the probe payload must be queued before any SID/SAS request so we can force the packet to have a full sid */
if (addr && (context->sender->last_probe==0 || now - context->sender->last_probe > interface->tick_ms*10))
if (addr && (context->sender->last_probe==0 || now - context->sender->last_probe > interface->destination.tick_ms*10))
overlay_send_probe(context->sender, *addr, interface, OQ_MESH_MANAGEMENT);
link_received_packet(context->sender, interface, context->sender_interface, sender_seq, packet_flags & PACKET_UNICAST);
@ -336,7 +336,7 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
if (packet_flags & PACKET_UNICAST)
context->addr=*addr;
else
context->addr=interface->broadcast_address;
context->addr=interface->destination.address;
}
RETURN(0);
OUT();

View File

@ -110,7 +110,7 @@ int overlay_frame_append_payload(struct decode_context *context, overlay_interfa
p->destination, p->source))
goto cleanup;
if (interface->encapsulation == ENCAP_OVERLAY){
if (interface->destination.encapsulation == ENCAP_OVERLAY){
if (ob_append_ui16(b, ob_position(p->payload)))
goto cleanup;
}

View File

@ -282,10 +282,11 @@ overlay_init_packet(struct outgoing_packet *packet, struct subscriber *destinati
if (unicast)
packet->unicast_subscriber = destination;
else
packet->seq = interface->sequence_number = (interface->sequence_number + 1)&0xFFFF;
ob_limitsize(packet->buffer, packet->interface->mtu);
packet->seq = interface->destination.sequence_number = (interface->destination.sequence_number + 1)&0xFFFF;
ob_limitsize(packet->buffer, packet->interface->destination.mtu);
overlay_packet_init_header(packet_version, interface->encapsulation, &packet->context, packet->buffer,
overlay_packet_init_header(packet_version, interface->destination.encapsulation,
&packet->context, packet->buffer,
destination, unicast, packet->i, packet->seq);
packet->header_length = ob_position(packet->buffer);
if (config.debug.overlayframes)
@ -334,7 +335,7 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){
// don't include interfaces which are currently transmitting using a serial buffer
if (frame->interface->tx_bytes_pending>0)
return 0;
next_allowed_packet = limit_next_allowed(&frame->interface->transfer_limit);
next_allowed_packet = limit_next_allowed(&frame->interface->destination.transfer_limit);
}else{
// check all interfaces
int i;
@ -345,7 +346,7 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){
if ((!frame->destination) && (frame->interface_sent_sequence[i]==FRAME_DONT_SEND ||
link_state_interface_oldest_neighbour(&overlay_interfaces[i])<0))
continue;
time_ms_t next_packet = limit_next_allowed(&overlay_interfaces[i].transfer_limit);
time_ms_t next_packet = limit_next_allowed(&overlay_interfaces[i].destination.transfer_limit);
if (next_packet < frame->interface_dont_send_until[i])
next_packet = frame->interface_dont_send_until[i];
if (next_allowed_packet==0||next_packet < next_allowed_packet)
@ -436,7 +437,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
frame->recvaddr = frame->next_hop->address;
frame->unicast = 1;
}else
frame->recvaddr = frame->interface->broadcast_address;
frame->recvaddr = frame->interface->destination.address;
// degrade packet version if required to reach the destination
if (frame->packet_version > frame->next_hop->max_packet_version)
@ -450,7 +451,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
if (frame->interface_sent_sequence[packet->i]==FRAME_DONT_SEND || frame->interface_dont_send_until[packet->i] >now)
goto skip;
frame->interface = packet->interface;
frame->recvaddr = packet->interface->broadcast_address;
frame->recvaddr = packet->interface->destination.address;
}else{
// find an interface that we haven't broadcast on yet
@ -465,11 +466,11 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
keep=1;
if (frame->interface_dont_send_until[i] >now)
continue;
time_ms_t next_allowed = limit_next_allowed(&overlay_interfaces[i].transfer_limit);
time_ms_t next_allowed = limit_next_allowed(&overlay_interfaces[i].destination.transfer_limit);
if (next_allowed > now)
continue;
frame->interface = &overlay_interfaces[i];
frame->recvaddr = overlay_interfaces[i].broadcast_address;
frame->recvaddr = overlay_interfaces[i].destination.address;
break;
}
@ -493,7 +494,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
}
// can we send a packet on this interface now?
if (limit_is_allowed(&frame->interface->transfer_limit))
if (limit_is_allowed(&frame->interface->destination.transfer_limit))
goto skip;
if (frame->source_full)
@ -504,7 +505,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
}else{
// is this packet going our way?
if (frame->interface!=packet->interface ||
frame->interface->encapsulation==ENCAP_SINGLE ||
frame->interface->destination.encapsulation==ENCAP_SINGLE ||
frame->packet_version!=packet->packet_version ||
memcmp(&packet->dest, &frame->recvaddr, sizeof(packet->dest))!=0){
goto skip;
@ -636,7 +637,7 @@ int overlay_send_tick_packet(struct overlay_interface *interface){
struct outgoing_packet packet;
bzero(&packet, sizeof(struct outgoing_packet));
packet.seq=-1;
overlay_init_packet(&packet, NULL, 0, 0, interface, interface->broadcast_address);
overlay_init_packet(&packet, NULL, 0, 0, interface, interface->destination.address);
overlay_fill_send_packet(&packet, gettime_ms());
return 0;

View File

@ -619,7 +619,7 @@ static int send_neighbour_link(struct neighbour *n)
if (n->subscriber->reachable & REACHABLE_DIRECT && (!(n->subscriber->reachable&REACHABLE_ASSUMED))){
frame->destination_resolved = 1;
frame->interface = n->subscriber->interface;
frame->recvaddr = frame->interface->broadcast_address;
frame->recvaddr = frame->interface->destination.address;
frame->resend=-1;
}
ob_limitsize(frame->payload, 400);
@ -641,7 +641,7 @@ static int send_neighbour_link(struct neighbour *n)
n->last_update = now;
}
n->next_neighbour_update = n->last_update + n->best_link->interface->tick_ms;
n->next_neighbour_update = n->last_update + n->best_link->interface->destination.tick_ms;
n->ack_counter = ACK_WINDOW;
OUT();
return 0;
@ -873,7 +873,7 @@ int link_received_packet(struct subscriber *subscriber, struct overlay_interface
if (neighbour->next_neighbour_update > now + 10);
neighbour->next_neighbour_update = now + 10;
}
link->link_timeout = now + (interface->tick_ms *5);
link->link_timeout = now + (interface->destination.tick_ms *5);
// force an update soon when we need to promptly ack packets
if (neighbour->using_us > now && neighbour->ack_counter <=0){
@ -1013,7 +1013,7 @@ int link_receive(overlay_mdp_frame *mdp)
version++;
}
neighbour->neighbour_link_timeout = now + interface->tick_ms * 5;
neighbour->neighbour_link_timeout = now + interface->destination.tick_ms * 5;
if (drop_rate != link->drop_rate || transmitter != link->transmitter)
version++;
@ -1118,10 +1118,10 @@ int link_state_legacy_ack(struct overlay_frame *frame, time_ms_t now)
// track the incoming link so we remember to send broadcasts
struct neighbour_link *nl = get_neighbour_link(neighbour, frame->interface, iface, 0);
nl->link_timeout = now + (frame->interface->tick_ms *5);
nl->link_timeout = now + (frame->interface->destination.tick_ms *5);
neighbour->legacy_protocol = 1;
neighbour->neighbour_link_timeout = now + link->interface->tick_ms * 5;
neighbour->neighbour_link_timeout = now + link->interface->destination.tick_ms * 5;
if (changed){
route_version++;

View File

@ -381,6 +381,45 @@ struct slip_decode_state{
int dst_offset;
};
struct overlay_interface;
struct network_destination {
struct overlay_interface *interface;
/* Number of milli-seconds per tick for this interface, which is basically related to the
the typical TX range divided by the maximum expected speed of nodes in the network.
This means that short-range communications has a higher bandwidth requirement than
long-range communications because the tick interval has to be shorter to still allow
fast-convergence time to allow for mobility.
For wifi (nominal range 100m) it is usually 500ms.
For ~100K ISM915MHz (nominal range 1000m) it will probably be about 5000ms.
For ~10K ISM915MHz (nominal range ~3000m) it will probably be about 15000ms.
These figures will be refined over time, and we will allow people to set them per-interface.
*/
unsigned tick_ms; /* milliseconds per tick */
// do we aggregate packets, or send one at a time
int encapsulation;
// time last packet was sent
time_ms_t last_tx;
// sequence number of last packet sent to this destination.
// Used to allow NACKs that can request retransmission of recent packets.
int sequence_number;
// rate limit for outgoing packets
struct limit_state transfer_limit;
/* Not necessarily the real MTU, but the largest frame size we are willing to TX.
For radio links the actual maximum and the maximum that is likely to be delivered reliably are
potentially two quite different values. */
int mtu;
// The IPv4 destination address, for an interface this will be the broadcast address.
struct sockaddr_in address;
};
typedef struct overlay_interface {
struct sched_ent alarm;
@ -398,7 +437,6 @@ typedef struct overlay_interface {
int port;
int type;
int socket_type;
int encapsulation;
char send_broadcasts;
char prefer_unicast;
// can we use this interface for routes to addresses in other subnets?
@ -411,47 +449,15 @@ typedef struct overlay_interface {
char point_to_point;
struct subscriber *other_device;
/* Number of milli-seconds per tick for this interface, which is basically related to the
the typical TX range divided by the maximum expected speed of nodes in the network.
This means that short-range communications has a higher bandwidth requirement than
long-range communications because the tick interval has to be shorter to still allow
fast-convergence time to allow for mobility.
For wifi (nominal range 100m) it is usually 500ms.
For ~100K ISM915MHz (nominal range 1000m) it will probably be about 5000ms.
For ~10K ISM915MHz (nominal range ~3000m) it will probably be about 15000ms.
These figures will be refined over time, and we will allow people to set them per-interface.
*/
unsigned tick_ms; /* milliseconds per tick */
unsigned int uartbps; // set serial port speed (which might be different from link speed)
int ctsrts; // enabled hardware flow control if non-zero
// time last packet was sent on this interface
time_ms_t last_tx;
struct network_destination destination;
struct subscriber *next_advert;
/* sequence number of last packet sent on this interface.
Used to allow NACKs that can request retransmission of recent packets.
*/
int sequence_number;
/* XXX need recent packet buffers to support the above */
struct limit_state transfer_limit;
/* We need to make sure that interface name and broadcast address is unique for all interfaces that are UP.
We bind a separate socket per interface / broadcast address Broadcast address and netmask, if known
We really only case about distinct broadcast addresses on interfaces.
Also simplifies aliases on interfaces. */
// the actual address of the interface.
struct sockaddr_in address;
struct sockaddr_in broadcast_address;
struct in_addr netmask;
/* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.
For radio links the actual maximum and the maximum that is likely to be delivered reliably are
potentially two quite different values. */
int mtu;
/* Use one of the INTERFACE_STATE_* constants to indicate the state of this interface.
If the interface stops working or disappears, it will be marked as DOWN and the socket closed.
But if it comes back up again, we should try to reuse this structure, even if the broadcast address has changed.