// ServiceKeynValue2FEnBE converts the given svcKey and svcValue to a frontend int the // form of L3n4AddrID and backend int he form of L3n4Addr. func ServiceKeynValue2FEnBE(svcKey ServiceKey, svcValue ServiceValue) (*types.L3n4AddrID, *types.L3n4Addr, error) { var ( beIP net.IP svcID types.ServiceID bePort uint16 ) if svcKey.IsIPv6() { svc6Val := svcValue.(*Service6Value) svcID = types.ServiceID(svc6Val.RevNat) beIP = svc6Val.Address.IP() bePort = svc6Val.Port } else { svc4Val := svcValue.(*Service4Value) svcID = types.ServiceID(svc4Val.RevNat) beIP = svc4Val.Address.IP() bePort = svc4Val.Port } feL3n4Addr, err := ServiceKey2L3n4Addr(svcKey) if err != nil { return nil, nil, fmt.Errorf("unable to create a new FE for service key %s: %s", svcKey, err) } beL3n4Addr, err := types.NewL3n4Addr(types.TCP, beIP, bePort) if err != nil { return nil, nil, fmt.Errorf("unable to create a new BE for IP: %s Port: %d: %s", beIP, bePort, err) } feL3n4AddrID := &types.L3n4AddrID{ L3n4Addr: *feL3n4Addr, ID: svcID, } return feL3n4AddrID, beL3n4Addr, nil }
// RevNatValue2L3n4AddrID converts the given RevNatKey and RevNatValue to a L3n4AddrID. func RevNatValue2L3n4AddrID(revNATKey RevNatKey, revNATValue RevNatValue) (*types.L3n4AddrID, error) { var ( svcID types.ServiceID be *types.L3n4Addr err error ) if revNATKey.IsIPv6() { revNat6Key := revNATKey.(*RevNat6Key) svcID = types.ServiceID(revNat6Key.Key) revNat6Value := revNATValue.(*RevNat6Value) be, err = RevNat6Value2L3n4Addr(revNat6Value) } else { revNat4Key := revNATKey.(*RevNat4Key) svcID = types.ServiceID(revNat4Key.Key) revNat4Value := revNATValue.(*RevNat4Value) be, err = RevNat4Value2L3n4Addr(revNat4Value) } if err != nil { return nil, err } return &types.L3n4AddrID{L3n4Addr: *be, ID: svcID}, nil }
func cliDeleteRevNat(ctx *cli.Context) { if ctx.Bool("all") { if err := client.RevNATDeleteAll(); err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } } else { if len(ctx.Args()) == 0 { cli.ShowCommandHelp(ctx, "delete-rev-nat") os.Exit(1) } id, err := strconv.ParseUint(ctx.Args().Get(0), 10, 16) if err != nil { cli.ShowCommandHelp(ctx, "delete-rev-nat") os.Exit(1) } if err := client.RevNATDelete(types.ServiceID(id)); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } } fmt.Printf("Successfully deleted\n") }
func parseRevNatKey(key string) types.ServiceID { k, err := strconv.ParseUint(key, 0, 16) if err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } return types.ServiceID(k) }
func verifyRevNATID(vars map[string]string) (types.ServiceID, error) { if val, exists := vars["revNATID"]; !exists { return 0, errors.New("server received rev NAT ID") } else { i, err := strconv.ParseUint(val, 10, 16) return types.ServiceID(i), err } }
func (c *ConsulClient) GASNewL3n4AddrID(basePath string, baseID uint32, lAddrID *types.L3n4AddrID) error { setIDtoL3n4Addr := func(lockPair *consulAPI.KVPair) error { defer c.KV().Release(lockPair, nil) lAddrID.ID = types.ServiceID(baseID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(lAddrID.ID), 10)) if err := c.SetValue(keyPath, lAddrID); err != nil { return err } return c.setMaxL3n4AddrID(baseID + 1) } session, _, err := c.Session().CreateNoChecks(nil, nil) if err != nil { return err } beginning := baseID for { log.Debugf("Trying to aquire a new free ID %d", baseID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(baseID), 10)) lockPair := &consulAPI.KVPair{Key: GetLockPath(keyPath), Session: session} acq, _, err := c.KV().Acquire(lockPair, nil) if err != nil { return err } if acq { svcKey, _, err := c.KV().Get(keyPath, nil) if err != nil { c.KV().Release(lockPair, nil) return err } if svcKey == nil { return setIDtoL3n4Addr(lockPair) } var consulL3n4AddrID types.L3n4AddrID if err := json.Unmarshal(svcKey.Value, &consulL3n4AddrID); err != nil { c.KV().Release(lockPair, nil) return err } if consulL3n4AddrID.ID == 0 { log.Infof("Recycling Service ID %d", baseID) return setIDtoL3n4Addr(lockPair) } c.KV().Release(lockPair, nil) } baseID++ if baseID > common.MaxSetOfServiceID { baseID = common.FirstFreeServiceID } if beginning == baseID { return fmt.Errorf("reached maximum set of serviceIDs available.") } } }
// GASNewL3n4AddrID gets the next available ServiceID and sets it in lAddrID. After // assigning the ServiceID to lAddrID it sets the ServiceID + 1 in // common.LastFreeServiceIDKeyPath path. func (e *EtcdClient) GASNewL3n4AddrID(basePath string, baseID uint32, lAddrID *types.L3n4AddrID) error { setIDtoL3n4Addr := func(id uint32) error { lAddrID.ID = types.ServiceID(id) keyPath := path.Join(basePath, strconv.FormatUint(uint64(lAddrID.ID), 10)) if err := e.SetValue(keyPath, lAddrID); err != nil { return err } return e.setMaxL3n4AddrID(id + 1) } acquireFreeID := func(firstID uint32, incID *uint32) error { log.Debugf("Trying to acquire a new free ID %d", *incID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(*incID), 10)) locker, err := e.LockPath(GetLockPath(keyPath)) if err != nil { return err } defer locker.Unlock() value, err := e.GetValue(keyPath) if err != nil { return err } if value == nil { return setIDtoL3n4Addr(*incID) } var consulL3n4AddrID types.L3n4AddrID if err := json.Unmarshal(value, &consulL3n4AddrID); err != nil { return err } if consulL3n4AddrID.ID == 0 { log.Infof("Recycling Service ID %d", *incID) return setIDtoL3n4Addr(*incID) } *incID++ if *incID > common.MaxSetOfServiceID { *incID = common.FirstFreeServiceID } if firstID == *incID { return fmt.Errorf("reached maximum set of serviceIDs available.") } return nil } var err error beginning := baseID for { if err = acquireFreeID(beginning, &baseID); err != nil { return err } else if beginning == baseID { return nil } } }
func (s *DaemonSuite) TestRevNATDeleteFail(c *C) { idWant := types.ServiceID(0) s.d.OnRevNATDelete = func(id types.ServiceID) error { c.Assert(id, DeepEquals, idWant) return errors.New("ID 0 is reserved") } err := s.c.RevNATDelete(idWant) c.Assert(err, ErrorMatches, ".*ID 0 is reserved.*") }
func (s *DaemonSuite) TestRevNATDeleteOK(c *C) { idWant := types.ServiceID(1) s.d.OnRevNATDelete = func(id types.ServiceID) error { c.Assert(id, DeepEquals, idWant) return nil } err := s.c.RevNATDelete(idWant) c.Assert(err, IsNil) }
func cliUpdateService(ctx *cli.Context) { feL3n4Addr := parseServiceKey(ctx.String("frontend")) backends := []types.L3n4Addr{} fe := types.L3n4AddrID{ ID: types.ServiceID(ctx.Int("id")), L3n4Addr: *feL3n4Addr, } backendList := ctx.StringSlice("backend") if len(backendList) == 0 { fmt.Printf("Reading backend list from stdin...\n") scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { backendList = append(backendList, scanner.Text()) } } for _, backend := range backendList { beAddr, err := net.ResolveTCPAddr("tcp", backend) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } be, err := types.NewL3n4Addr(types.TCP, beAddr.IP, uint16(beAddr.Port)) if err != nil { fmt.Fprintf(os.Stderr, "Unable to create a new L3n4Addr for backend %s: %s\n", backend, err) os.Exit(1) } if !be.IsIPv6() && fe.IsIPv6() { fmt.Fprintf(os.Stderr, "Address mismatch between frontend and backend %s\n", backend) os.Exit(1) } if fe.Port == 0 && beAddr.Port != 0 { fmt.Fprintf(os.Stderr, "L4 backend found (%v) with L3 frontend\n", beAddr) os.Exit(1) } backends = append(backends, *be) } if err := client.SVCAdd(fe, backends, addRev); err != nil { fmt.Fprintf(os.Stderr, "Unable to add the service: %s\n", err) os.Exit(1) } fmt.Printf("Added %d backends\n", len(backends)) }
func (s *DaemonSuite) TestRevNATAddFail(c *C) { idWant := types.ServiceID(0) s.d.OnRevNATAdd = func(id types.ServiceID, revNAT types.L3n4Addr) error { c.Assert(id, DeepEquals, idWant) c.Assert(revNAT, DeepEquals, revNat1) return errors.New("ID 0 is reserved") } err := s.c.RevNATAdd(idWant, revNat1) c.Assert(err, ErrorMatches, ".*ID 0 is reserved.*") }
func (s *DaemonSuite) TestRevNATGetFail(c *C) { idWant := types.ServiceID(0) s.d.OnRevNATGet = func(id types.ServiceID) (*types.L3n4Addr, error) { c.Assert(id, DeepEquals, idWant) return nil, errors.New("ID 0 is reserved") } revNat1Received, err := s.c.RevNATGet(idWant) c.Assert(err, ErrorMatches, ".*ID 0 is reserved.*") c.Assert(revNat1Received, IsNil) }
func (s *DaemonSuite) TestRevNATGetOK(c *C) { idWant := types.ServiceID(1) s.d.OnRevNATGet = func(id types.ServiceID) (*types.L3n4Addr, error) { c.Assert(id, DeepEquals, idWant) return &revNat1, nil } revNat1Received, err := s.c.RevNATGet(idWant) c.Assert(err, IsNil) c.Assert(*revNat1Received, DeepEquals, revNat1) }
func (s *DaemonSuite) TestRevNATAddOK(c *C) { idWant := types.ServiceID(1) s.d.OnRevNATAdd = func(id types.ServiceID, revNAT types.L3n4Addr) error { c.Assert(id, DeepEquals, idWant) c.Assert(revNAT, DeepEquals, revNat1) return nil } err := s.c.RevNATAdd(idWant, revNat1) c.Assert(err, IsNil) }
func (cli *LBClient) SVCGet(feL3n4 types.L3n4Addr) (*types.LBSVC, error) { key := lbmap.L3n4Addr2ServiceKey(feL3n4) svc, err := lbmap.LookupService(key) if err != nil { return nil, err } besLen := 0 if key.IsIPv6() { besLen = int(svc.(*lbmap.Service6Value).Count) } else { besLen = int(svc.(*lbmap.Service4Value).Count) } bes := []types.L3n4Addr{} svcID := types.ServiceID(0) for i := 1; i <= besLen; i++ { key.SetBackend(i) svc, err := lbmap.LookupService(key) if err != nil { return nil, err } sv, err := lbmap.ServiceValue2L3n4Addr(key, svc) if err != nil { return nil, err } bes = append(bes, *sv) if i == 1 { svcID = types.ServiceID(svc.RevNatKey().GetKey()) } } return &types.LBSVC{ FE: types.L3n4AddrID{ ID: svcID, L3n4Addr: feL3n4, }, BES: bes, }, nil }
func (s *CiliumNetClientSuite) TestRevNATDeleteOK(c *C) { id := types.ServiceID(2016) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c.Assert(r.Method, Equals, "DELETE") c.Assert(r.URL.Path, Equals, "/lb/revnat/"+strconv.FormatUint(uint64(id), 10)) w.WriteHeader(http.StatusNoContent) })) defer server.Close() cli := NewTestClient(server.URL, c) err := cli.RevNATDelete(id) c.Assert(err, Equals, nil) }
func (s *CiliumNetClientSuite) TestRevNATDeleteFail(c *C) { id := types.ServiceID(2016) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c.Assert(r.Method, Equals, "DELETE") c.Assert(r.URL.Path, Equals, "/lb/revnat/"+strconv.FormatUint(uint64(id), 10)) w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/json") e := json.NewEncoder(w) err := e.Encode(types.ServerError{Code: -1, Text: "daemon didn't complete your request"}) c.Assert(err, Equals, nil) })) defer server.Close() cli := NewTestClient(server.URL, c) err := cli.RevNATDelete(id) c.Assert(strings.Contains(err.Error(), "daemon didn't complete your request"), Equals, true) }
func cliUpdateRevNat(ctx *cli.Context) { tcpAddr, err := net.ResolveTCPAddr("tcp", ctx.String("address")) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } val, err := types.NewL3n4Addr(types.TCP, tcpAddr.IP, uint16(tcpAddr.Port)) if err != nil { fmt.Fprintf(os.Stderr, "Unable to create a new L3n4Addr: %s\n", err) os.Exit(1) } id := types.ServiceID(ctx.Int("id")) if err := client.RevNATAdd(id, *val); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } }
func (ds *DaemonSuite) TestServices(c *C) { var nilL3n4AddrID *types.L3n4AddrID // Set up last free ID with zero id, err := ds.d.GetMaxServiceID() c.Assert(err, Equals, nil) c.Assert(id, Equals, common.FirstFreeServiceID) ffsIDu16 := types.ServiceID(uint16(common.FirstFreeServiceID)) l3n4AddrID, err := ds.d.PutL3n4Addr(l3n4Addr1, 0) c.Assert(err, Equals, nil) c.Assert(l3n4AddrID.ID, Equals, ffsIDu16) l3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr1, 0) c.Assert(err, Equals, nil) c.Assert(l3n4AddrID.ID, Equals, ffsIDu16) l3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr2, 0) c.Assert(err, Equals, nil) c.Assert(l3n4AddrID.ID, Equals, ffsIDu16+1) gotL3n4AddrID, err := ds.d.GetL3n4AddrID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) wantL3n4AddrID.ID = ffsIDu16 wantL3n4AddrID.L3n4Addr = l3n4Addr1 c.Assert(gotL3n4AddrID, DeepEquals, wantL3n4AddrID) err = ds.d.DeleteL3n4AddrIDByUUID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) gotL3n4AddrID, err = ds.d.GetL3n4AddrID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID, Equals, nilL3n4AddrID) gotL3n4AddrID, err = ds.d.GetL3n4AddrID(common.FirstFreeServiceID + 1) c.Assert(err, Equals, nil) wantL3n4AddrID.ID = types.ServiceID(common.FirstFreeServiceID + 1) wantL3n4AddrID.L3n4Addr = l3n4Addr2 c.Assert(gotL3n4AddrID, DeepEquals, wantL3n4AddrID) err = ds.d.DeleteL3n4AddrIDByUUID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) err = ds.d.kvClient.SetMaxID(common.LastFreeServiceIDKeyPath, common.FirstFreeServiceID, common.FirstFreeServiceID) c.Assert(err, Equals, nil) err = ds.d.DeleteL3n4AddrIDByUUID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) gotL3n4AddrID, err = ds.d.GetL3n4AddrID(common.FirstFreeServiceID) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID, Equals, nilL3n4AddrID) gotL3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr2, 0) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID.ID, Equals, types.ServiceID(common.FirstFreeServiceID+1)) sha256sum, err := l3n4Addr2.SHA256Sum() c.Assert(err, Equals, nil) gotL3n4AddrID, err = ds.d.GetL3n4AddrIDBySHA256(sha256sum) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID, DeepEquals, wantL3n4AddrID) err = ds.d.DeleteL3n4AddrIDBySHA256(sha256sum) c.Assert(err, Equals, nil) err = ds.d.DeleteL3n4AddrIDByUUID(common.FirstFreeServiceID + 1) c.Assert(err, Equals, nil) err = ds.d.DeleteL3n4AddrIDByUUID(common.FirstFreeServiceID + 1) c.Assert(err, Equals, nil) gotL3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr2, 0) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID.ID, Equals, ffsIDu16) gotL3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr1, 0) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID.ID, Equals, types.ServiceID(common.FirstFreeServiceID+1)) gotL3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr1, 99) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID.ID, Equals, types.ServiceID(common.FirstFreeServiceID+1)) err = ds.d.DeleteL3n4AddrIDByUUID(uint32(common.FirstFreeServiceID + 1)) c.Assert(err, Equals, nil) gotL3n4AddrID, err = ds.d.PutL3n4Addr(l3n4Addr1, 99) c.Assert(err, Equals, nil) c.Assert(gotL3n4AddrID.ID, Equals, types.ServiceID(99)) }