Skip to content

Commit ab555e2

Browse files
committed
Use complete port configs when plumbing mark rules
Currently, a reference counting scheme is used to reference count all individual port configs that need to be plumbed in the ingress to make sure that in situations where a service with the same set of port configs is getting added or removed doesn't accidentally remove the port config plumbing if the add/remove notifications come out of order. This same reference counting scheme is also used for plumbing the port-based marking rules. But marking rules should not be plumbed based on that because marks are always different for different instantiations of the same service. So fixed the code to plumb port-based mark rules based on the complete set of port configs, while plumbing pure port rules and proxies based on a filter set of port configs based on the reference count. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
1 parent d271945 commit ab555e2

1 file changed

Lines changed: 76 additions & 39 deletions

File tree

service_linux.go

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -380,17 +380,17 @@ func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*P
380380
}
381381

382382
if addService {
383-
var iPorts []*PortConfig
383+
var filteredPorts []*PortConfig
384384
if sb.ingress {
385-
iPorts = filterPortConfigs(ingressPorts, false)
386-
if err := programIngress(gwIP, iPorts, false); err != nil {
385+
filteredPorts = filterPortConfigs(ingressPorts, false)
386+
if err := programIngress(gwIP, filteredPorts, false); err != nil {
387387
logrus.Errorf("Failed to add ingress: %v", err)
388388
return
389389
}
390390
}
391391

392-
logrus.Debugf("Creating service for vip %s fwMark %d ingressPorts %#v", vip, fwMark, iPorts)
393-
if err := invokeFWMarker(sb.Key(), vip, fwMark, iPorts, eIP, false); err != nil {
392+
logrus.Debugf("Creating service for vip %s fwMark %d ingressPorts %#v", vip, fwMark, ingressPorts)
393+
if err := invokeFWMarker(sb.Key(), vip, fwMark, ingressPorts, filteredPorts, eIP, false); err != nil {
394394
logrus.Errorf("Failed to add firewall mark rule in sbox %s: %v", sb.Key(), err)
395395
return
396396
}
@@ -453,15 +453,15 @@ func (sb *sandbox) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po
453453
logrus.Errorf("Failed to delete a new service for vip %s fwmark %d: %v", vip, fwMark, err)
454454
}
455455

456-
var iPorts []*PortConfig
456+
var filteredPorts []*PortConfig
457457
if sb.ingress {
458-
iPorts = filterPortConfigs(ingressPorts, true)
459-
if err := programIngress(gwIP, iPorts, true); err != nil {
458+
filteredPorts = filterPortConfigs(ingressPorts, true)
459+
if err := programIngress(gwIP, filteredPorts, true); err != nil {
460460
logrus.Errorf("Failed to delete ingress: %v", err)
461461
}
462462
}
463463

464-
if err := invokeFWMarker(sb.Key(), vip, fwMark, iPorts, eIP, true); err != nil {
464+
if err := invokeFWMarker(sb.Key(), vip, fwMark, ingressPorts, filteredPorts, eIP, true); err != nil {
465465
logrus.Errorf("Failed to add firewall mark rule in sbox %s: %v", sb.Key(), err)
466466
}
467467
}
@@ -715,33 +715,66 @@ func plumbProxy(iPort *PortConfig, isDelete bool) error {
715715
return nil
716716
}
717717

718+
func writePortsToFile(ports []*PortConfig) (string, error) {
719+
f, err := ioutil.TempFile("", "port_configs")
720+
if err != nil {
721+
return "", err
722+
}
723+
defer f.Close()
724+
725+
buf, err := proto.Marshal(&EndpointRecord{
726+
IngressPorts: ports,
727+
})
728+
729+
n, err := f.Write(buf)
730+
if err != nil {
731+
return "", err
732+
}
733+
734+
if n < len(buf) {
735+
return "", io.ErrShortWrite
736+
}
737+
738+
return f.Name(), nil
739+
}
740+
741+
func readPortsFromFile(fileName string) ([]*PortConfig, error) {
742+
buf, err := ioutil.ReadFile(fileName)
743+
if err != nil {
744+
return nil, err
745+
}
746+
747+
var epRec EndpointRecord
748+
err = proto.Unmarshal(buf, &epRec)
749+
if err != nil {
750+
return nil, err
751+
}
752+
753+
return epRec.IngressPorts, nil
754+
}
755+
718756
// Invoke fwmarker reexec routine to mark vip destined packets with
719757
// the passed firewall mark.
720-
func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, isDelete bool) error {
721-
var ingressPortsFile string
758+
func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, filteredPorts []*PortConfig, eIP *net.IPNet, isDelete bool) error {
759+
var (
760+
ingressPortsFile string
761+
filteredPortsFile string
762+
)
763+
722764
if len(ingressPorts) != 0 {
723-
f, err := ioutil.TempFile("", "port_configs")
765+
var err error
766+
ingressPortsFile, err = writePortsToFile(ingressPorts)
724767
if err != nil {
725768
return err
726769
}
770+
}
727771

728-
buf, err := proto.Marshal(&EndpointRecord{
729-
IngressPorts: ingressPorts,
730-
})
731-
732-
n, err := f.Write(buf)
772+
if len(filteredPorts) != 0 {
773+
var err error
774+
filteredPortsFile, err = writePortsToFile(filteredPorts)
733775
if err != nil {
734-
f.Close()
735776
return err
736777
}
737-
738-
if n < len(buf) {
739-
f.Close()
740-
return io.ErrShortWrite
741-
}
742-
743-
ingressPortsFile = f.Name()
744-
f.Close()
745778
}
746779

747780
addDelOpt := "-A"
@@ -751,7 +784,7 @@ func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*Port
751784

752785
cmd := &exec.Cmd{
753786
Path: reexec.Self(),
754-
Args: append([]string{"fwmarker"}, path, vip.String(), fmt.Sprintf("%d", fwMark), addDelOpt, ingressPortsFile, eIP.String()),
787+
Args: append([]string{"fwmarker"}, path, vip.String(), fmt.Sprintf("%d", fwMark), addDelOpt, ingressPortsFile, filteredPortsFile, eIP.String()),
755788
Stdout: os.Stdout,
756789
Stderr: os.Stderr,
757790
}
@@ -768,27 +801,29 @@ func fwMarker() {
768801
runtime.LockOSThread()
769802
defer runtime.UnlockOSThread()
770803

771-
if len(os.Args) < 7 {
804+
if len(os.Args) < 8 {
772805
logrus.Error("invalid number of arguments..")
773806
os.Exit(1)
774807
}
775808

776809
var ingressPorts []*PortConfig
810+
var filteredPorts []*PortConfig
777811
if os.Args[5] != "" {
778-
buf, err := ioutil.ReadFile(os.Args[5])
812+
var err error
813+
ingressPorts, err = readPortsFromFile(os.Args[5])
779814
if err != nil {
780-
logrus.Errorf("Failed to read ports config file: %v", err)
815+
logrus.Errorf("Failed reading ingress ports file: %v", err)
781816
os.Exit(6)
782817
}
818+
}
783819

784-
var epRec EndpointRecord
785-
err = proto.Unmarshal(buf, &epRec)
820+
if os.Args[6] != "" {
821+
var err error
822+
filteredPorts, err = readPortsFromFile(os.Args[6])
786823
if err != nil {
787-
logrus.Errorf("Failed to unmarshal ports config data: %v", err)
824+
logrus.Errorf("Failed reading filtered ports file: %v", err)
788825
os.Exit(7)
789826
}
790-
791-
ingressPorts = epRec.IngressPorts
792827
}
793828

794829
vip := os.Args[2]
@@ -800,12 +835,14 @@ func fwMarker() {
800835
addDelOpt := os.Args[4]
801836

802837
rules := [][]string{}
803-
for _, iPort := range ingressPorts {
838+
for _, iPort := range filteredPorts {
804839
rule := strings.Fields(fmt.Sprintf("-t nat %s PREROUTING -p %s --dport %d -j REDIRECT --to-port %d",
805840
addDelOpt, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort))
806841
rules = append(rules, rule)
842+
}
807843

808-
rule = strings.Fields(fmt.Sprintf("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d",
844+
for _, iPort := range ingressPorts {
845+
rule := strings.Fields(fmt.Sprintf("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d",
809846
addDelOpt, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, fwMark))
810847
rules = append(rules, rule)
811848
}
@@ -823,9 +860,9 @@ func fwMarker() {
823860
}
824861

825862
if addDelOpt == "-A" {
826-
eIP, subnet, err := net.ParseCIDR(os.Args[6])
863+
eIP, subnet, err := net.ParseCIDR(os.Args[7])
827864
if err != nil {
828-
logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[6], err)
865+
logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[7], err)
829866
os.Exit(9)
830867
}
831868

0 commit comments

Comments
 (0)