Goby v2
route.cpp
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #include "goby/common/logger.h"
24 #include "goby/util/as.h"
25 
26 #include "route.h"
27 
28 using goby::glog;
29 using goby::util::as;
30 using namespace goby::common::logger;
31 
32 void goby::acomms::RouteManager::set_cfg(const protobuf::RouteManagerConfig& cfg)
33 {
34  cfg_ = cfg;
35  process_cfg();
36 }
37 
38 void goby::acomms::RouteManager::merge_cfg(const protobuf::RouteManagerConfig& cfg)
39 {
40  cfg_.MergeFrom(cfg);
41  process_cfg();
42 }
43 
44 void goby::acomms::RouteManager::process_cfg()
45 {
46  glog.is(DEBUG1) && glog << group("goby::acomms::route")
47  << "Route is: " << cfg_.route().DebugString() << std::endl;
48 }
49 
50 void goby::acomms::RouteManager::handle_in(const protobuf::QueuedMessageMeta& meta,
51  const google::protobuf::Message& data_msg, int modem_id)
52 {
53  if (meta.dest() == modem_id) // no routing to do ...
54  return;
55 
56  glog.is(DEBUG1) && glog << group("goby::acomms::route") << "Incoming message "
57  << data_msg.GetDescriptor()->full_name()
58  << ", can we route message to destination: " << meta.dest() << "?"
59  << std::endl;
60 
61  int next_hop = find_next_hop(modem_id, meta.dest());
62 
63  if (next_hop != -1)
64  {
65  uint32 subnet = next_hop & cfg_.subnet_mask();
66  glog.is(DEBUG1) && glog << group("goby::acomms::route")
67  << "Requeuing to proper subnet: " << subnet << " (" << std::hex
68  << next_hop << " & " << cfg_.subnet_mask() << ")" << std::dec
69  << std::endl;
70  if (!subnet_map_.count(subnet))
71  {
72  glog.is(DEBUG1) && glog << group("goby::acomms::route")
73  << "No subnet available for this message, ignoring."
74  << std::endl;
75  return;
76  }
77 
78  subnet_map_[subnet]->push_message(data_msg, &meta);
79  }
80  else
81  {
82  glog.is(DEBUG1) && glog << group("goby::acomms::route")
83  << "Destination is not in route, ignoring." << std::endl;
84  }
85 }
86 
87 int goby::acomms::RouteManager::route_index(int modem_id)
88 {
89  for (int i = 0, n = cfg_.route().hop_size(); i < n; ++i)
90  {
91  if (cfg_.route().hop(i) == modem_id)
92  return i;
93  }
94  return -1;
95 }
96 
97 void goby::acomms::RouteManager::handle_out(protobuf::QueuedMessageMeta* meta,
98  const google::protobuf::Message& data_msg, int modem_id)
99 {
100  glog.is(DEBUG1) && glog << group("goby::acomms::route")
101  << "Trying to route outgoing message to destination: " << meta->dest()
102  << std::endl;
103 
104  int next_hop = find_next_hop(modem_id, meta->dest());
105  if (next_hop != -1)
106  {
107  meta->set_dest(next_hop);
108  glog.is(DEBUG1) && glog << group("goby::acomms::route")
109  << "Set next hop to: " << meta->dest() << std::endl;
110  }
111 }
112 
113 int goby::acomms::RouteManager::find_next_hop(int us, int dest)
114 {
115  int next_hop = find_next_route_hop(us, dest);
116  if (next_hop == -1 && cfg_.has_default_gateway())
117  {
118  next_hop = cfg_.default_gateway();
119  glog.is(DEBUG1) && glog << group("goby::acomms::route")
120  << "Using default gateway: " << next_hop << std::endl;
121  }
122  return next_hop;
123 }
124 
125 int goby::acomms::RouteManager::find_next_route_hop(int us, int dest)
126 {
127  int current_route_index = route_index(us);
128 
129  if (current_route_index == -1)
130  {
131  glog.is(DEBUG1) && glog << group("goby::acomms::route")
132  << "Current modem id is not in route." << std::endl;
133  return -1;
134  }
135 
136  int dest_route_index = route_index(dest);
137 
138  if (dest_route_index == -1)
139  {
140  glog.is(DEBUG1) && glog << group("goby::acomms::route")
141  << "Destination modem id is not in route." << std::endl;
142  return -1;
143  }
144 
145  int direction;
146  if (dest_route_index < current_route_index)
147  direction = -1;
148  else if (dest_route_index > current_route_index)
149  direction = 1;
150  else
151  direction = 0;
152 
153  int next_hop_index = current_route_index + direction;
154 
155  if (next_hop_index < 0 || next_hop_index >= cfg_.route().hop_size())
156  {
157  glog.is(DEBUG1) && glog << warn << group("goby::acomms::route") << "Next hop index ("
158  << next_hop_index << ") is not in route." << std::endl;
159  return -1;
160  }
161 
162  return cfg_.route().hop(next_hop_index);
163 }
164 
165 void goby::acomms::RouteManager::add_subnet_queue(QueueManager* manager)
166 {
167  if (!manager)
168  {
169  glog.is(DEBUG1) && glog << warn << group("goby::acomms::route")
170  << "Null manager passed to add_subnet_queue. Ignoring."
171  << std::endl;
172  return;
173  }
174 
175  uint32 modem_id = manager->modem_id();
176  uint32 subnet = modem_id & cfg_.subnet_mask();
177 
178  if (subnet_map_.count(subnet))
179  glog.is(DEBUG1) && glog << warn << group("goby::acomms::route") << "Subnet " << subnet
180  << " already mapped. Replacing." << std::endl;
181 
182  subnet_map_[subnet] = manager;
183 
184  glog.is(DEBUG1) && glog << group("goby::acomms::route") << "Adding subnet (hex: " << std::hex
185  << subnet << std::dec << ")" << std::endl;
186 }
google::protobuf::uint32 uint32
an unsigned 32 bit integer
common::FlexOstream glog
Access the Goby logger through this object.