Use any packet as a self-announce

Stop sending OF_TYPE_SELFANNOUNCE
Deprecate OF_TYPE_DATA_VOICE
Tweak payload priorities
Don't allow client applications to send high priority payloads
This commit is contained in:
Jeremy Lakeman 2012-12-16 10:05:32 +10:30
parent 55be5208a9
commit 82db15db5b
14 changed files with 61 additions and 187 deletions

View File

@ -81,7 +81,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/* All of these types should be considered deprecated. Processing code should migrate to well known MDP port numbers */
/* Overlay mesh packet codes */
#define OF_TYPE_SELFANNOUNCE 0x10 /* BATMAN style announcement frames */
#define OF_TYPE_SELFANNOUNCE_ACK 0x20 /* BATMAN style "I saw your announcment" frames */
#define OF_TYPE_DATA 0x30 /* Ordinary data frame.
Upto MTU bytes of payload.

View File

@ -41,6 +41,7 @@ static void directory_send(struct subscriber *directory_service, const unsigned
bcopy(sid, request.out.src.sid, SID_SIZE);
request.out.src.port=MDP_PORT_NOREPLY;
request.out.queue=OQ_ORDINARY;
bcopy(directory_service->sid, request.out.dst.sid, SID_SIZE);
request.out.dst.port=MDP_PORT_DIRECTORY;

View File

@ -1239,6 +1239,7 @@ int keyring_mapping_request(keyring_file *k, overlay_mdp_frame *req)
overlay_mdp_swap_src_dst(req);
req->out.ttl=0;
req->packetTypeAndFlags=MDP_TX; /* crypt and sign */
req->out.queue=OQ_MESH_MANAGEMENT;
if (config.debug.keyring)
DEBUGF("Sending SID:SAS mapping, %d bytes, %s:0x%X -> %s:0x%X",
req->out.payload_length,
@ -1275,6 +1276,7 @@ int keyring_send_sas_request(struct subscriber *subscriber){
memset(&mdp,0,sizeof(overlay_mdp_frame));
mdp.packetTypeAndFlags=MDP_TX;
mdp.out.queue=OQ_MESH_MANAGEMENT;
bcopy(subscriber->sid,mdp.out.dst.sid,SID_SIZE);
mdp.out.dst.port=MDP_PORT_KEYMAPREQUEST;
mdp.out.src.port=MDP_PORT_KEYMAPREQUEST;

View File

@ -73,6 +73,7 @@ struct subscriber{
time_ms_t last_stun_request;
time_ms_t last_probe;
time_ms_t last_rx;
time_ms_t last_acked;
time_ms_t last_tx;
// public signing key details for remote peers

View File

@ -121,8 +121,6 @@ int overlay_route_add_advertisements(struct decode_context *context, overlay_int
if (!my_subscriber)
return WHY("Cannot advertise because I don't know who I am");
ob_checkpoint(e);
if (overlay_frame_build_header(context, e,
0, OF_TYPE_NODEANNOUNCE, 0, 1,
NULL, NULL,
@ -145,7 +143,7 @@ int overlay_route_add_advertisements(struct decode_context *context, overlay_int
struct subscriber *start = next_advertisement;
next_advertisement=NULL;
int start_pos = ob_position(e);
ob_checkpoint(e);
// append announcements starting from the last node we couldn't advertise last time
enum_subscribers(start, add_advertisement, e);
@ -155,12 +153,8 @@ int overlay_route_add_advertisements(struct decode_context *context, overlay_int
enum_subscribers(NULL, add_advertisement, e);
}
if (ob_position(e) == start_pos){
// no advertisements? don't bother to send the payload at all.
ob_rewind(e);
}else
ob_patch_rfs(e);
ob_patch_rfs(e);
return 0;
}

View File

@ -597,7 +597,7 @@ void overlay_dummy_poll(struct sched_ent *alarm)
(struct sockaddr*)&packet.src_addr, sizeof(packet.src_addr))) {
WARN("Unsupported packet from dummy interface");
}
}else
}else if (config.debug.packetrx)
DEBUGF("Ignoring packet addressed to %s:%d", inet_ntoa(packet.dst_addr.sin_addr), ntohs(packet.dst_addr.sin_port));
}

View File

@ -211,7 +211,7 @@ int load_subscriber_address(struct subscriber *subscriber)
}
}
DEBUGF("Loaded address %s:%d for %s", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), alloca_tohex_sid(subscriber->sid));
return overlay_send_probe(subscriber, addr, interface);
return overlay_send_probe(subscriber, addr, interface, OQ_MESH_MANAGEMENT);
}
/* Collection of unicast echo responses to detect working links */
@ -240,7 +240,7 @@ overlay_mdp_service_probe(overlay_mdp_frame *mdp)
RETURN(0);
}
int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface){
int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface, int queue){
if (interface==NULL)
interface = overlay_interface_find(addr.sin_addr, 1);
@ -258,7 +258,7 @@ int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay
frame->source = my_subscriber;
frame->next_hop = frame->destination = peer;
frame->ttl=1;
frame->queue=OQ_ORDINARY;
frame->queue=queue;
frame->destination_resolved=1;
frame->recvaddr=addr;
frame->unicast=1;
@ -344,6 +344,7 @@ int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp)
bcopy(mdp->out.dst.sid, reply.out.src.sid, SID_SIZE);
reply.out.src.port=MDP_PORT_STUNREQ;
reply.out.dst.port=MDP_PORT_STUN;
reply.out.queue=OQ_MESH_MANAGEMENT;
struct overlay_buffer *replypayload = ob_static(reply.out.payload, sizeof(reply.out.payload));
@ -400,7 +401,7 @@ int overlay_mdp_service_stun(overlay_mdp_frame *mdp)
if (!subscriber || (subscriber->reachable!=REACHABLE_NONE))
continue;
overlay_send_probe(subscriber, addr, NULL);
overlay_send_probe(subscriber, addr, NULL, OQ_MESH_MANAGEMENT);
}
ob_free(buff);
@ -431,6 +432,7 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ
bcopy(server->sid, mdp.out.dst.sid, SID_SIZE);
mdp.out.src.port=MDP_PORT_STUN;
mdp.out.dst.port=MDP_PORT_STUNREQ;
mdp.out.queue=OQ_MESH_MANAGEMENT;
struct overlay_buffer *payload = ob_static(mdp.out.payload, sizeof(mdp.out.payload));
overlay_address_append(NULL, payload, request);

View File

@ -481,6 +481,7 @@ int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const unsigned char
overlay_mdp_frame mdpreply;
bzero(&mdpreply, sizeof mdpreply);
mdpreply.packetTypeAndFlags = MDP_TX; // outgoing MDP message
mdpreply.out.queue=OQ_ORDINARY;
memcpy(mdpreply.out.src.sid, resolved_sid, SID_SIZE);
mdpreply.out.src.port = MDP_PORT_DNALOOKUP;
bcopy(dstaddr, &mdpreply.out.dst, sizeof(sockaddr_mdp));
@ -647,9 +648,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
}
}
/* give voice packets priority */
if (mdp->out.dst.port==MDP_PORT_VOMP) frame->type=OF_TYPE_DATA_VOICE;
else frame->type=OF_TYPE_DATA;
frame->type=OF_TYPE_DATA;
frame->prev=NULL;
frame->next=NULL;
struct overlay_buffer *plaintext=ob_new();
@ -772,12 +771,6 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
if (frame->queue==0)
frame->queue = OQ_ORDINARY;
/* Make sure only voice traffic gets priority */
if (frame->type==OF_TYPE_DATA_VOICE) {
frame->queue=OQ_ISOCHRONOUS_VOICE;
rhizome_saw_voice_traffic();
}
frame->send_copies = mdp->out.send_copies;
if (overlay_payload_enqueue(frame))
@ -884,7 +877,7 @@ static void overlay_mdp_scan(struct sched_ent *alarm)
while(state->current <= stop){
addr.sin_addr.s_addr=htonl(state->current);
if (addr.sin_addr.s_addr != state->interface->address.sin_addr.s_addr){
if (overlay_send_probe(NULL, addr, state->interface))
if (overlay_send_probe(NULL, addr, state->interface, OQ_ORDINARY))
break;
}
state->current++;
@ -965,6 +958,10 @@ void overlay_mdp_poll(struct sched_ent *alarm)
case MDP_TX: /* Send payload (and don't treat it as system privileged) */
if (config.debug.mdprequests) DEBUG("MDP_TX");
// Dont allow mdp clients to send very high priority payloads
if (mdp->out.queue<=OQ_MESH_MANAGEMENT)
mdp->out.queue=OQ_ORDINARY;
overlay_mdp_dispatch(mdp,1,(struct sockaddr_un*)recvaddr,recvaddrlen);
return;
break;

View File

@ -154,7 +154,7 @@ static void parse_frame(struct overlay_buffer *buff){
if (context.sender->reachable==REACHABLE_NONE){
set_reachable(context.sender, REACHABLE_UNICAST|REACHABLE_ASSUMED);
overlay_send_probe(context.sender, context.sender->address, interface);
overlay_send_probe(context.sender, context.sender->address, interface, OQ_MESH_MANAGEMENT);
}
}

View File

@ -68,12 +68,6 @@ int process_incoming_frame(time_ms_t now, struct overlay_interface *interface, s
int id = (interface - overlay_interfaces);
switch(f->type)
{
// route control frames
case OF_TYPE_SELFANNOUNCE:
if (config.debug.overlayframes)
DEBUG("Processing OF_TYPE_SELFANNOUNCE");
overlay_route_saw_selfannounce(f,now);
break;
case OF_TYPE_SELFANNOUNCE_ACK:
if (config.debug.overlayframes)
DEBUG("Processing OF_TYPE_SELFANNOUNCE_ACK");
@ -103,7 +97,7 @@ int process_incoming_frame(time_ms_t now, struct overlay_interface *interface, s
process_explain(f);
break;
default:
RETURN(WHYF("Support for f->type=0x%x not yet implemented",f->type));
RETURN(WHYF("Support for f->type=0x%x not implemented",f->type));
}
RETURN(0);
}
@ -130,12 +124,6 @@ int overlay_forward_payload(struct overlay_frame *f){
if (!qf)
RETURN(WHY("Could not clone frame for queuing"));
/* Make sure voice traffic gets priority */
if (qf->type==OF_TYPE_DATA_VOICE) {
qf->queue=OQ_ISOCHRONOUS_VOICE;
rhizome_saw_voice_traffic();
}
if (overlay_payload_enqueue(qf)) {
op_free(qf);
RETURN(WHY("failed to enqueue forwarded payload"));
@ -251,14 +239,25 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
context.sender->address = f.recvaddr;
// if this is a dummy announcement for a node that isn't in our routing table
if (context.sender->reachable == REACHABLE_NONE &&
(!context.sender->node) &&
packet_flags&PACKET_UNICAST){
// mark this subscriber as reachable directly via unicast.
if (context.sender->reachable == REACHABLE_NONE) {
context.sender->interface = interface;
set_reachable(context.sender, REACHABLE_UNICAST|REACHABLE_ASSUMED);
overlay_send_probe(context.sender, f.recvaddr, interface);
// assume for the moment, that we can reply with the same packet type
if (packet_flags&PACKET_UNICAST){
/* Note the probe payload must be queued before any SID/SAS request so we can force the packet to have a full sid */
overlay_send_probe(context.sender, f.recvaddr, interface, OQ_MESH_MANAGEMENT);
set_reachable(context.sender, REACHABLE_UNICAST|REACHABLE_ASSUMED);
}else{
set_reachable(context.sender, REACHABLE_BROADCAST|REACHABLE_ASSUMED);
}
}
if ((!(packet_flags&PACKET_UNICAST)) && context.sender->last_acked + interface->tick_ms <= now){
overlay_route_ack_selfannounce(interface,
context.sender->last_acked>now - 3*interface->tick_ms?context.sender->last_acked:now,
now,sender_interface,context.sender);
context.sender->last_acked = now;
}
}
@ -354,14 +353,14 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
f.modifiers=flags;
// TODO allow for one byte length
int payload_len = ob_get_ui16(b);
unsigned int payload_len = ob_get_ui16(b);
if (payload_len <=0){
WHY("Unable to parse payload length");
if (payload_len > ob_remaining(b)){
WHYF("Unable to parse payload length (%d)", payload_len);
break;
}
int next_payload = b->position + payload_len;
int next_payload = ob_position(b) + payload_len;
if (f.source)
f.source->last_rx = now;
@ -386,13 +385,13 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
if (!process && !forward)
goto next;
f.payload = ob_slice(b, b->position, next_payload - b->position);
f.payload = ob_slice(b, b->position, payload_len);
if (!f.payload){
WHY("Payload length is longer than remaining packet size");
break;
}
// mark the entire payload as having valid data
ob_limitsize(f.payload, next_payload - b->position);
ob_limitsize(f.payload, payload_len);
// forward payloads that are for someone else or everyone
if (forward){
@ -418,61 +417,3 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
RETURN(0);
}
int overlay_add_selfannouncement(struct decode_context *context, int interface,struct overlay_buffer *b)
{
/* Pull the first record from the HLR database and turn it into a
self-announcment. These are shorter than regular Subscriber Observation
Notices (SON) because they are just single-hop announcments of presence.
Do we really need to push the whole SID (32 bytes), or will just, say,
8 do so that we use a prefix of the SID which is still very hard to forge?
A hearer of a self-announcement who has not previously seen the sender might
like to get some authentication to prevent naughty people from spoofing routes.
We can do this by having ourselves, the sender, keep track of the last few frames
we have sent, so that we can be asked to sign them. Actually, we won't sign them,
as that is too slow/energy intensive, but we could use a D-H exchange with the neighbour,
performed once to get a shared secret that can be used to feed a stream cipher to
produce some sort of verification.
XXX - But this functionality really needs to move up a level to whole frame composition.
*/
time_ms_t now = gettime_ms();
if (overlay_frame_build_header(context, b,
0, OF_TYPE_SELFANNOUNCE, 0, 1,
NULL, NULL,
NULL, my_subscriber))
return -1;
/* Sequence number range. Based on one tick per millisecond. */
time_ms_t last_ms = overlay_interfaces[interface].last_tick_ms;
// If this interface has not been ticked yet (no selfannounce sent) then invent the prior sequence
// number: one millisecond ago.
if (last_ms == -1)
last_ms = now - 1;
if (ob_append_ui32(b, last_ms))
return WHY("Could not add low sequence number to self-announcement");
if (ob_append_ui32(b, now))
return WHY("Could not add high sequence number to self-announcement");
if (config.debug.overlayinterfaces)
DEBUGF("interface #%d: last_tick_ms=%lld, now=%lld (delta=%lld)",
interface,
(long long)overlay_interfaces[interface].last_tick_ms,
(long long)now,
(long long)(now - last_ms)
);
overlay_interfaces[interface].last_tick_ms = now;
/* A byte that indicates which interface we are sending over */
if (ob_append_byte(b,interface))
return WHY("Could not add interface number to self-announcement");
ob_patch_rfs(b);
return 0;
}

View File

@ -214,6 +214,8 @@ int overlay_payload_enqueue(struct overlay_frame *p)
queue->last=p;
if (!queue->first) queue->first=p;
queue->length++;
if (p->queue==OQ_ISOCHRONOUS_VOICE)
rhizome_saw_voice_traffic();
overlay_update_queue_schedule(queue, p);
@ -235,14 +237,8 @@ overlay_init_packet(struct outgoing_packet *packet, struct subscriber *destinati
overlay_packet_init_header(&packet->context, packet->buffer, destination, unicast, packet->i, 0);
packet->header_length = ob_position(packet->buffer);
if (tick){
/* 1. Send announcement about ourselves, including one SID that we host if we host more than one SID
(the first SID we host becomes our own identity, saving a little bit of data here).
*/
overlay_add_selfannouncement(&packet->context, packet->i, packet->buffer);
/* Add advertisements for ROUTES */
overlay_route_add_advertisements(&packet->context, packet->interface, packet->buffer);
}
}

View File

@ -194,10 +194,10 @@ overlay_node *get_node(struct subscriber *subscriber, int create){
return subscriber->node;
}
int overlay_route_ack_selfannounce(struct overlay_frame *f,
int overlay_route_ack_selfannounce(overlay_interface *recv_interface,
unsigned int s1,unsigned int s2,
int interface,
struct overlay_neighbour *n)
struct subscriber *subscriber)
{
/* Acknowledge the receipt of a self-announcement of an immediate neighbour.
We could acknowledge immediately, but that requires the transmission of an
@ -234,16 +234,10 @@ int overlay_route_ack_selfannounce(struct overlay_frame *f,
XXX 6 is quite an arbitrary selection however. */
/* Set destination of ack to source of observed frame */
out->destination = n->node->subscriber;
out->destination = subscriber;
/* set source to ourselves */
out->source = my_subscriber;
/* Assume immediate neighbour via broadcast packet if we don't have a route yet */
if (out->destination->reachable == REACHABLE_NONE){
out->destination->interface=f->interface;
set_reachable(out->destination, REACHABLE_ASSUMED|REACHABLE_BROADCAST);
}
/* Set the time in the ack. Use the last sequence number we have seen
from this neighbour, as that may be helpful information for that neighbour
down the track. My policy is to communicate that information which should
@ -263,36 +257,6 @@ int overlay_route_ack_selfannounce(struct overlay_frame *f,
on the return path doesn't count against the link. */
ob_append_ui32(out->payload,s1);
ob_append_ui32(out->payload,s2);
/* The ack needs to contain the per-interface scores that we have built up
for this neighbour.
We expect that for most neighbours they will have many fewer than 32 interfaces,
and even when they have multiple interfaces that we will only be able to hear
them on one or a few.
So we will structure the format so that we use fewer bytes when fewer interfaces
are involved.
Probably the simplest is to put each non-zero score followed by it's interface.
That way the whole list will be easy to parse, and as short as 3 bytes for a
single interface.
We could use the spare 2 bits at the top of the interface id to indicate
multiple interfaces with same score?
*/
#ifdef NOTDEFINED
int i;
for(i=0;i<OVERLAY_MAX_INTERFACES;i++)
{
/* Only include interfaces with score >0 */
if (n->scores[i]) {
ob_append_byte(out->payload,n->scores[i]);
ob_append_byte(out->payload,i);
}
}
/* Terminate list */
ob_append_byte(out->payload,0);
#endif
ob_append_byte(out->payload,interface);
/* Add to queue. Keep broadcast status that we have assigned here if required to
@ -412,33 +376,6 @@ int overlay_route_node_can_hear_me(struct subscriber *subscriber, int sender_int
return 0;
}
int overlay_route_saw_selfannounce(struct overlay_frame *f, time_ms_t now)
{
IN();
unsigned int s1,s2;
unsigned char sender_interface;
overlay_node *node = get_node(f->source, 1);
if (!node)
RETURN(-1);
struct overlay_neighbour *n=overlay_route_get_neighbour_structure(node, 1 /* make neighbour if not yet one */);
if (!n){
RETURN(-1);
}
s1=ob_get_ui32(f->payload);
s2=ob_get_ui32(f->payload);
sender_interface=ob_get(f->payload);
if (config.debug.overlayrouting)
DEBUGF("Received self-announcement for sequence range [%08x,%08x] from interface %d",s1,s2,sender_interface);
overlay_route_ack_selfannounce(f,s1,s2,sender_interface,n);
RETURN(0);
}
/* XXX Think about scheduling this node's score for readvertising? */
int overlay_route_recalc_node_metrics(overlay_node *n, time_ms_t now)
{
@ -527,7 +464,7 @@ int overlay_route_recalc_node_metrics(overlay_node *n, time_ms_t now)
if (old_best && !best_score){
INFOF("PEER UNREACHABLE, sid=%s", alloca_tohex_sid(n->subscriber->sid));
overlay_send_probe(n->subscriber, n->subscriber->address, n->subscriber->interface);
overlay_send_probe(n->subscriber, n->subscriber->address, n->subscriber->interface, OQ_MESH_MANAGEMENT);
}else if(best_score && !old_best){
INFOF("PEER REACHABLE, sid=%s", alloca_tohex_sid(n->subscriber->sid));

View File

@ -453,7 +453,6 @@ int overlay_frame_resolve_addresses(struct overlay_frame *f);
time_ms_t overlay_time_until_next_tick();
int overlay_add_selfannouncement(struct decode_context *context, int interface,struct overlay_buffer *b);
int overlay_frame_append_payload(struct decode_context *context, overlay_interface *interface,
struct overlay_frame *p, struct overlay_buffer *b);
int overlay_packet_init_header(struct decode_context *context, struct overlay_buffer *buff,
@ -503,7 +502,10 @@ typedef struct overlay_node {
} overlay_node;
int overlay_route_saw_selfannounce_ack(struct overlay_frame *f, time_ms_t now);
int overlay_route_saw_selfannounce(struct overlay_frame *f, time_ms_t now);
int overlay_route_ack_selfannounce(overlay_interface *recv_interface,
unsigned int s1,unsigned int s2,
int interface,
struct subscriber *subscriber);
overlay_node *overlay_route_find_node(const unsigned char *sid,int prefixLen,int createP);
int overlayServerMode();
@ -730,7 +732,7 @@ void server_config_reload(struct sched_ent *alarm);
void server_shutdown_check(struct sched_ent *alarm);
void overlay_mdp_poll(struct sched_ent *alarm);
int overlay_mdp_try_interal_services(overlay_mdp_frame *mdp);
int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface);
int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface, int queue);
int overlay_send_stun_request(struct subscriber *server, struct subscriber *request);
void fd_periodicstats(struct sched_ent *alarm);
void rhizome_check_connections(struct sched_ent *alarm);

4
vomp.c
View File

@ -490,7 +490,7 @@ static int vomp_send_status_remote(struct vomp_call_state *call)
bzero(&mdp,sizeof(mdp));
prepare_vomp_header(call, &mdp);
mdp.out.queue=OQ_ORDINARY;
if (call->local.state < VOMP_STATE_RINGINGOUT && call->remote.state < VOMP_STATE_RINGINGOUT) {
int didLen;
unsigned char codecs[CODEC_FLAGS_LENGTH];
@ -559,6 +559,8 @@ int vomp_received_audio(struct vomp_call_state *call, int audio_codec, int time,
// send the payload more than once to add resilience to dropped packets
// TODO remove once network links have built in retries
mdp.out.send_copies=VOMP_MAX_RECENT_SAMPLES;
mdp.out.queue=OQ_ISOCHRONOUS_VOICE;
overlay_mdp_dispatch(&mdp,0,NULL,0);
return 0;