router.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package udp
  2. import (
  3. "net"
  4. "sync"
  5. log "github.com/coreos-inc/kolach/Godeps/_workspace/src/github.com/golang/glog"
  6. "github.com/coreos-inc/kolach/pkg"
  7. )
  8. const (
  9. minIP4HdrSize = 20
  10. )
  11. type routeEntry struct {
  12. sn pkg.IP4Net
  13. addr *net.UDPAddr
  14. }
  15. type Router struct {
  16. mux sync.Mutex
  17. port int
  18. routes []routeEntry
  19. }
  20. func NewRouter(port int) *Router {
  21. return &Router{
  22. port: port,
  23. }
  24. }
  25. func (r *Router) SetRoute(sn pkg.IP4Net, dst pkg.IP4) {
  26. r.mux.Lock()
  27. defer r.mux.Unlock()
  28. for _, re := range r.routes {
  29. if re.sn.Equal(sn) {
  30. re.addr = &net.UDPAddr{
  31. IP: dst.ToIP(),
  32. Port: r.port,
  33. }
  34. return
  35. }
  36. }
  37. re := routeEntry{
  38. sn: sn,
  39. addr: &net.UDPAddr{
  40. IP: dst.ToIP(),
  41. Port: r.port,
  42. },
  43. }
  44. r.routes = append(r.routes, re)
  45. }
  46. func (r *Router) DelRoute(sn pkg.IP4Net) {
  47. r.mux.Lock()
  48. defer r.mux.Unlock()
  49. for i, re := range r.routes {
  50. if re.sn.Equal(sn) {
  51. r.routes[i] = r.routes[len(r.routes)-1]
  52. r.routes = r.routes[:len(r.routes)-1]
  53. return
  54. }
  55. }
  56. }
  57. func (r *Router) routePacket(pkt []byte, conn *net.UDPConn) {
  58. if len(pkt) < minIP4HdrSize {
  59. log.V(1).Infof("Packet too small (%d bytes), unable to route", len(pkt))
  60. return
  61. }
  62. r.mux.Lock()
  63. defer r.mux.Unlock()
  64. dstIP := pkg.FromBytes(pkt[16:20])
  65. for i, re := range r.routes {
  66. if re.sn.Contains(dstIP) {
  67. nbytes, err := conn.WriteToUDP(pkt, re.addr)
  68. if err != nil || nbytes != len(pkt) {
  69. if err != nil {
  70. log.V(1).Info("UDP write failed with: ", err)
  71. } else {
  72. log.V(1).Infof("Was only able to send %d out of %d bytes to %s: ", nbytes, len(pkt), re.addr.IP)
  73. }
  74. }
  75. // packets for same dest tend to come in burst. swap to front make it faster for subsequent ones
  76. if i != 0 {
  77. r.routes[0], r.routes[i] = r.routes[i], r.routes[0]
  78. }
  79. return
  80. }
  81. }
  82. log.V(1).Info("No route found for ", dstIP)
  83. }