CONNECTIVITY 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. This document describes how nodes in a VPN find and connect to eachother and
  2. maintain a stable network.
  3. Copyright 2001-2002 Guus Sliepen <guus@sliepen.eu.org>
  4. Permission is granted to make and distribute verbatim copies of
  5. this documentation provided the copyright notice and this
  6. permission notice are preserved on all copies.
  7. Permission is granted to copy and distribute modified versions of
  8. this documentation under the conditions for verbatim copying,
  9. provided that the entire resulting derived work is distributed
  10. under the terms of a permission notice identical to this one.
  11. $Id: CONNECTIVITY,v 1.1.2.9 2002/06/21 10:11:10 guus Exp $
  12. 1. Problem
  13. ==========
  14. We have a set of nodes (A, B, C, ...) that are part of the same VPN. They need
  15. to connect to eachother and form a single graph that satisfies the tree
  16. property.
  17. There is the possibility that loops are formed, the offending connections must
  18. be eliminated.
  19. Suppose we start with two smaller graphs that want to form a single larger
  20. graph. Both graphs consist of three nodes:
  21. A-----B-----C
  22. D-----E-----F
  23. It is very well possible that A wants to connect to D, and F wants to connect
  24. to C, both at the same time. The following loop will occur:
  25. A-----B-----C
  26. | ^
  27. | |
  28. v |
  29. D-----E-----F
  30. The situation described here is totally symmetric, there is no preference to
  31. one connection over the other. The problem of resolving the loop, maintaining
  32. consistency and stability is therefore not a trivial one.
  33. What happens when A---D and C---F are connected to eachother? They exchange
  34. lists of known hosts. A knows of B and C, and D knows of E and F. The protocol
  35. defines ADD_HOST messages, from now on we will say that "node X sends and
  36. ADD_HOST(Y) to Z".
  37. There are two possible scenarios: either both A---D and C---F finish
  38. authentication at the same time, or A---D finishes first, so that ADD_HOST
  39. messages will reach C and F before they finish authentication.
  40. 1.1 A---D finishes first
  41. ------------------------
  42. After A---D authentication finishes the following actions are taken:
  43. 1 A sends ADD_HOST(B) to D
  44. A sends ADD_HOST(C) to D
  45. D sends ADD_HOST(E) to A
  46. D sends ADD_HOST(F) to A
  47. 2 A sends ADD_HOST(D) to B
  48. A receives ADD_HOST(E) from D:
  49. A sends ADD_HOST(E) to B
  50. A receives ADD_HOST(F) from D:
  51. A sends ADD_HOST(F) to B
  52. D sends ADD_HOST(A) to E
  53. D receives ADD_HOST(B) from A:
  54. D sends ADD_HOST(B) to E
  55. D receives ADD_HOST(C) from A:
  56. D sends ADD_HOST(C) to E
  57. 3 B receives ADD_HOST(D) from A,
  58. B sends ADD_HOST(D) to C
  59. B receives ADD_HOST(E) from A:
  60. B sends ADD_HOST(E) to C
  61. B receives ADD_HOST(F) from A:
  62. B sends ADD_HOST(F) to C
  63. E receives ADD_HOST(A) from D:
  64. E sends ADD_HOST(A) to F
  65. E receives ADD_HOST(B) from D:
  66. E sends ADD_HOST(B) to F
  67. E receives ADD_HOST(C) from D:
  68. E sends ADD_HOST(C) to F
  69. 4 C receives ADD_HOST(D) from B.
  70. C receives ADD_HOST(E) from B.
  71. C receives ADD_HOST(F) from B.
  72. F receives ADD_HOST(A) from E.
  73. F receives ADD_HOST(B) from E.
  74. F receives ADD_HOST(C) from E.
  75. Then C---F authentication finishes, the following actions are taken:
  76. 1 C notes that F is already known:
  77. Connection is closed.
  78. F notes that C is already known:
  79. Connection is closed.
  80. 1.2 Both A---D and C---F finish at the same time.
  81. -------------------------------------------------
  82. 1 A sends ADD_HOST(B) to D
  83. A sends ADD_HOST(C) to D
  84. D sends ADD_HOST(E) to A
  85. D sends ADD_HOST(F) to A
  86. C sends ADD_HOST(A) to F
  87. C sends ADD_HOST(B) to F
  88. F sends ADD_HOST(D) to C
  89. F sends ADD_HOST(E) to C
  90. 2 A sends ADD_HOST(D) to B
  91. A receives ADD_HOST(E) from D:
  92. A sends ADD_HOST(E) to B
  93. A receives ADD_HOST(F) from D:
  94. A sends ADD_HOST(F) to B
  95. D sends ADD_HOST(A) to E
  96. D receives ADD_HOST(B) from A:
  97. D sends ADD_HOST(B) to E
  98. D receives ADD_HOST(C) from A:
  99. D sends ADD_HOST(C) to E
  100. C sends ADD_HOST(F) to B
  101. C receives ADD_HOST(D) from F:
  102. A sends ADD_HOST(D) to B
  103. C receives ADD_HOST(E) from F:
  104. A sends ADD_HOST(E) to B
  105. F sends ADD_HOSTS(C) to E
  106. F receives ADD_HOST(A) from C:
  107. D sends ADD_HOST(A) to E
  108. F receives ADD_HOST(B) from C:
  109. D sends ADD_HOST(B) to E
  110. 3 B receives ADD_HOST(D) from A,
  111. B sends ADD_HOST(D) to C
  112. B receives ADD_HOST(E) from A:
  113. B sends ADD_HOST(E) to C
  114. B receives ADD_HOST(F) from A:
  115. B sends ADD_HOST(F) to C
  116. E receives ADD_HOST(A) from D:
  117. E sends ADD_HOST(A) to F
  118. E receives ADD_HOST(B) from D:
  119. E sends ADD_HOST(B) to F
  120. E receives ADD_HOST(C) from D:
  121. E sends ADD_HOST(C) to F
  122. B receives ADD_HOST(F) from C, and notes that is is already known:
  123. <insert solution here>
  124. B receives ADD_HOST(D) from C, and notes that is is already known:
  125. <insert solution here>
  126. B receives ADD_HOST(E) from C, and notes that is is already known:
  127. <insert solution here>
  128. E receives ADD_HOST(C) from F, and notes that is is already known:
  129. <insert solution here>
  130. E receives ADD_HOST(A) from F, and notes that is is already known:
  131. <insert solution here>
  132. E receives ADD_HOST(B) from F, and notes that is is already known:
  133. <insert solution here>
  134. 4 A receives ADD_HOST(D) from B, and notes that it is already known:
  135. <insert solution here>
  136. A receives ADD_HOST(E) from B, and notes that it is already known:
  137. <insert solution here>
  138. A receives ADD_HOST(F) from B, and notes that it is already known:
  139. <insert solution here>
  140. F receives ADD_HOST(A) from E, and notes that it is already known:
  141. <insert solution here>
  142. F receives ADD_HOST(B) from E, and notes that it is already known:
  143. <insert solution here>
  144. F receives ADD_HOST(B) from E, and notes that it is already known:
  145. <insert solution here>
  146. ...
  147. 1.2.1 Augmenting ADD_HOST
  148. -------------------------
  149. A solution would be to augment ADD_HOST with an extra parameter, the nexthop of
  150. the added host:
  151. 3 B receives ADD_HOST(D,A) from A,
  152. B sends ADD_HOST(D,A) to C
  153. B receives ADD_HOST(E,D) from A:
  154. B sends ADD_HOST(E,D) to C
  155. B receives ADD_HOST(F,E) from A:
  156. B sends ADD_HOST(F,E) to C
  157. E receives ADD_HOST(A,D) from D:
  158. E sends ADD_HOST(A,D) to F
  159. E receives ADD_HOST(B,A) from D:
  160. E sends ADD_HOST(B,A) to F
  161. E receives ADD_HOST(C,B) from D:
  162. E sends ADD_HOST(C,B) to F
  163. B receives ADD_HOST(F,C) from C, and notes that F is already known:
  164. <insert solution here>
  165. B receives ADD_HOST(D,E) from C, and notes that D is already known:
  166. <insert solution here>
  167. B receives ADD_HOST(E,F) from C, and notes that E is already known:
  168. <insert solution here>
  169. E receives ADD_HOST(C,F) from F, and notes that C is already known:
  170. <insert solution here>
  171. E receives ADD_HOST(A,B) from F, and notes that A is already known:
  172. <insert solution here>
  173. E receives ADD_HOST(B,C) from F, and notes that B is already known:
  174. <insert solution here>
  175. So, B and E have to make a choice. Which ADD_HOST is going to win? Fortunately,
  176. since the ADD_HOST messages are augmented, they have an extra piece of
  177. information they can use to decide in a deterministic way which one is going to
  178. win. For example, B got ADD_HOST(F,E) and ADD_HOST(F,C). Since "E" > "C", it
  179. could let ADD_HOST(F,E) win.
  180. B receives ADD_HOST(F,C) from C, and notes that F is already known:
  181. since "C" < "E", B ignores ADD_HOST(F,E)
  182. B sends ADD_HOST(F,C) to A
  183. ...
  184. E receives ADD_HOST(C,F) from F, and notes that C is already known:
  185. since "F" > "B", E removes the ADD_HOST(C,B) in favour of the new one
  186. E sends ADD_HOST(C,F) to D
  187. 4 A receives ADD_HOST(F,E) from B, and notes that F is already known:
  188. since "E" < "D", A ignores ADD_HOST(F,D).
  189. ...
  190. D receives ADD_HOST(C,F) from E, and notes that C is already known:
  191. since "F" > "B", D removes the ADD_HOST(C,B),
  192. closes the connection with C, in favour of the new one.
  193. Ok, time to forget this crap.
  194. 1.2.2
  195. -----
  196. The problem with the current ADD/DEL_HOST technique is that each host only
  197. knows the general direction in which to send packets for the other hosts. It
  198. really doesn't know much about the true topology of the network, only about
  199. it's direct neighbours. With so little information each host cannot make a
  200. certain decision which it knows for sure all the others will decide too.
  201. Let's do something totally different. Instead of notifying every host of the
  202. addition of a new host, which is represented by a vertex in a graph, lets send
  203. out notifications of new connections, which are the edges in a graph. This is
  204. rather cheap, since our graphs are (almost) spanning trees, there is
  205. approximately one edge for each vertex in the graph, so we don't need to send
  206. more messages. Furthermore, an edge is characterized by two vertices, so we
  207. only send a fixed amount of extra information. The size/complexity of the
  208. problem therefore does not increase much.
  209. What is the advantage of notifying each vertex of new edges instead of new
  210. vertices? Well, all the vertices now know exactly which connections are made
  211. between each host. This was not known with the former schemes.
  212. Ok back to our problem:
  213. A-----B-----C
  214. D-----E-----F
  215. Edges are undirected, and are characterised by the vertices it connects, sorted
  216. alphabetically, so the edges in the two graphs are:
  217. (A,B), (B,C), (D,E) and (E,F).
  218. So again we have that A wants to connect to D, and F wants to connect to C,
  219. both at the same time. The following loop will occur:
  220. A-----B-----C
  221. | ^
  222. | |
  223. v |
  224. D-----E-----F
  225. Instead of sending ADD_HOSTs, lets assume the hosts send ADD_EDGEs. So, after
  226. making the connections:
  227. 1 A sends ADD_EDGE(A,D) to B
  228. A sends ADD_EDGE(A,B) to D
  229. A sends ADD_EDGE(B,C) to D
  230. D sends ADD_EDGE(A,D) to E
  231. D sends ADD_EDGE(D,E) to A
  232. D sends ADD_EDGE(E,F) to A
  233. C sends ADD_EDGE(C,F) to B
  234. C sends ADD_EDGE(A,B) to F
  235. C sends ADD_EDGE(B,C) to F
  236. F sends ADD_EDGE(C,F) to E
  237. F sends ADD_EDGE(D,E) to C
  238. F sends ADD_EDGE(E,F) to C
  239. 2 B receives ADD_EDGE(A,D) from A:
  240. B sends ADD_EDGE(A,D) to C
  241. B receives ADD_EDGE(D,E) from A:
  242. B sends ADD_EDGE(D,E) to C
  243. B receives ADD_EDGE(E,F) from A:
  244. B sends ADD_EDGE(E,F) to C
  245. ...
  246. B receives ADD_EDGE(C,F) from C, notes that both C and F are already known,
  247. but that the edge (C,F) was not known, so a loop has been created:
  248. <resolve loop here>
  249. Ok, how to resolve the loop? Remeber, we want to do that in such a way that it
  250. is consistent with the way all the other hosts resolve the loop. Here is the
  251. things B does when it notices that a loop is going to be formed:
  252. B performs a Breadth First Search from the first element of the list of all
  253. known hosts sorted alfabetically, in this case A, and thereby finds a
  254. spanning tree. (This might later be changed into a minimum spanning tree
  255. alhorithm, but the key point here is that all hosts do this with exactly the
  256. same starting parameters.) All known edges that are not in the spanning tree
  257. are marked inactive.
  258. An edge marked inactive does not mean anything, unless this edge is connected
  259. to B itself. In that case, B will stop sending messages over that edge. B might
  260. consider closing this edge, but this is not really needed. Keeping it means no
  261. DEL_EDGE has to be sent for it, and if another edge is removed (which will
  262. quite certainly split the graph if it's a spanning tree), this edge might be
  263. reactivated, without the need of sending a new ADD_EDGE for it. On the other
  264. hand, we mustn't keep to many inactive edges, because we want to keep the
  265. number of known edges linear to the number of hosts (otherwise the size of the
  266. problem will grow quadratically).
  267. So, since B didn't deactivate one of it's own edges, it forwards the
  268. ADD_EDGE(C,F) to A, which also does a BFS, and so on, until it reaches F. F of
  269. course also does a BFS, notes that is is one of it's own edges. It deactivates
  270. the edge (C,F), and consequently will not forward the ADD_EDGE(C,F) to C
  271. anymore. In the mean time, C got messages from B which will make C do the same.
  272. Ok, suppose a DEL_EDGE was sent, and it means an inactive edge has to be
  273. reactivated. The vertices connected by that edge must exchange their entire
  274. knowledge of edges again, because in the mean time other messages could have
  275. been sent, which were not properly forwarded. Take this example:
  276. X C-----D
  277. | | |
  278. | | |
  279. v | |
  280. A-----B- - -E
  281. The edge (B,E) is inactive. X is trying to make a new connection with A. A
  282. sends an ADD_EDGE(A,X) to B, which forwards it to C. At that time, the
  283. connection between C and D goes down, so C sends a DEL_EDGE(C,D) to B, and D
  284. sends a DEL_EDGE(C,D) to E. If we just allow (B,E) to be reactivated again
  285. without anything else, then E and D will never have received the ADD_EDGE(A,X).
  286. So, B and E have to exchange edges again, and propagate them to the hosts they
  287. already know.