-
Notifications
You must be signed in to change notification settings - Fork 4
/
service.go
110 lines (93 loc) · 2.2 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package clusterf
import (
"fmt"
"github.com/qmsk/clusterf/config"
"github.com/qmsk/clusterf/ipvs"
"net"
"syscall"
)
type Service struct {
ipvs.Service
dests ServiceDests
}
type ServiceDests map[string]Dest
func (dests ServiceDests) get(ipvsDest ipvs.Dest) Dest {
if dest, exists := dests[ipvsDest.String()]; exists {
return dest
} else {
dest := Dest{
Dest: ipvsDest,
}
dests[dest.String()] = dest
return dest
}
}
func (dests ServiceDests) sync(ipvsDest ipvs.Dest) {
// for side-effect
_ = dests.get(ipvsDest)
}
func (dests ServiceDests) config(ipvsDest ipvs.Dest) {
dest, exists := dests[ipvsDest.String()]
if exists {
// merge
dest.Weight += ipvsDest.Weight
} else {
dest = Dest{
Dest: ipvsDest,
}
}
dests[ipvsDest.String()] = dest
}
// Lookup or initialize an ipvsService from a config ServiceFrontend
func configServiceFrontend(ipvsType ipvsType, frontend *config.ServiceFrontend, options IPVSOptions) (*ipvs.Service, error) {
if frontend == nil {
return nil, nil
}
ipvsService := ipvs.Service{
Af: ipvsType.Af,
Protocol: ipvsType.Protocol,
SchedName: options.SchedName,
Timeout: 0,
Flags: ipvs.Flags{Flags: 0, Mask: 0xffffffff},
Netmask: 0xffffffff,
}
switch ipvsType.Af {
case syscall.AF_INET:
if frontend.IPv4 == "" {
return nil, nil
} else if ip := net.ParseIP(frontend.IPv4); ip == nil {
return nil, fmt.Errorf("Invalid IPv4: %v", frontend.IPv4)
} else if ip4 := ip.To4(); ip4 == nil {
return nil, fmt.Errorf("Invalid IPv4: %v", ip)
} else {
ipvsService.Addr = ip4
}
case syscall.AF_INET6:
if frontend.IPv6 == "" {
return nil, nil
} else if ip := net.ParseIP(frontend.IPv6); ip == nil {
return nil, fmt.Errorf("Invalid IPv6: %v", frontend.IPv6)
} else if ip16 := ip.To16(); ip16 == nil {
return nil, fmt.Errorf("Invalid IPv6: %v", ip)
} else {
ipvsService.Addr = ip16
}
}
switch ipvsType.Protocol {
case syscall.IPPROTO_TCP:
if frontend.TCP == 0 {
return nil, nil
} else {
ipvsService.Port = frontend.TCP
}
case syscall.IPPROTO_UDP:
if frontend.UDP == 0 {
return nil, nil
} else {
ipvsService.Port = frontend.UDP
}
default:
panic("invalid proto")
}
return &ipvsService, nil
}