Skip to content

Commit

Permalink
Initial app
Browse files Browse the repository at this point in the history
  • Loading branch information
stano45 committed Aug 7, 2024
1 parent 6acd0c9 commit dd8ef51
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 105 deletions.
35 changes: 35 additions & 0 deletions examples/redis/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
include ../../utils/Makefile

all: compile build control

terminals: h1 h2 h3 h4

build: clean
./build.sh

clean:
./clean.sh

migrate:
@if [ "${SOURCE}" = "" ] || [ "${TARGET}" = "" ]; then \
echo "Usage: make migrate SOURCE=x TARGET=y"; \
else \
./cr.sh ${SOURCE} ${TARGET}; \
fi

redis-app:
sudo podman build -t redis-app -f app/Containerfile app

h1:
xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h1" -hold -e "sudo podman rm -f tcp-client && sudo podman run --name tcp-client --pod h1-pod tcp-client" &

h2:
xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h2" -hold -e "sudo podman logs -f h2" &

h3:
xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h3" -hold -e "sudo podman logs -f h3" &

h4:
xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h4" -hold -e "sudo podman logs -f h4" &

.PHONY: all terminals build clean migrate h1 h2 h3 h4
28 changes: 28 additions & 0 deletions examples/redis/app/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM golang:1.22.2 as builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY main.go .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags '-extldflags "-static"' -o main .

FROM alpine:latest

RUN apk --no-cache add ca-certificates

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /home/appuser/

COPY --from=builder /app/main .

RUN chmod +x ./main

USER appuser

EXPOSE 8080

CMD ["./main", "-redisAddr=10.0.1.10:6379"]
10 changes: 10 additions & 0 deletions examples/redis/app/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/stano45/p4containerflow/examples/redis/app

go 1.22.2

require github.com/go-redis/redis/v8 v8.11.5

require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)
24 changes: 24 additions & 0 deletions examples/redis/app/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
58 changes: 58 additions & 0 deletions examples/redis/app/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"flag"
"fmt"
"log"
"net/http"
"github.com/go-redis/redis/v8"
"context"
"encoding/json"
)

type Server struct {
RedisClient *redis.Client
}

var ctx = context.Background()

func (s *Server) getData(w http.ResponseWriter, r *http.Request) {
key := r.URL.Query().Get("key")
if key == "" {
http.Error(w, "Key is missing", http.StatusBadRequest)
return
}

val, err := s.RedisClient.Get(ctx, key).Result()
if err == redis.Nil {
http.Error(w, "Key not found", http.StatusNotFound)
return
} else if err != nil {
http.Error(w, "Error fetching data from Redis", http.StatusInternalServerError)
return
}

response := map[string]string{
"key": key,
"value": val,
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}

func main() {
redisAddr := flag.String("redisAddr", "localhost:6379", "Address of the Redis server")
flag.Parse()

rdb := redis.NewClient(&redis.Options{
Addr: *redisAddr,
})

server := &Server{RedisClient: rdb}

http.HandleFunc("/get", server.getData)

fmt.Println("Server is running on port 8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
66 changes: 66 additions & 0 deletions examples/redis/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash

NUM_HOSTS=3

# Container image and arguments
REDIS_IMG="docker.io/redis:latest"
REDIS_ARGS=""

APP_IMG="redis-app"
APP_ARGS=""

# Host 1
printf "\n-----Creating host 1-----\n"
sudo podman network create --driver bridge --opt isolate=1 --disable-dns --interface-name h1-br --gateway 10.0.1.10 --subnet 10.0.1.0/24 h1-net
sudo podman pod create --name h1-pod --network h1-net --mac-address 08:00:00:00:01:01 --ip 10.0.1.1
sudo podman run --detach --privileged --name redis-app --pod h1-pod --cap-add NET_ADMIN $APP_IMG $APP_ARGS

# Host 2
printf "\n-----Creating host 2-----\n"
sudo podman network create --driver bridge --opt isolate=1 --disable-dns --interface-name h2-br --gateway 10.0.2.20 --route 10.0.1.0/24,10.0.2.20 --subnet 10.0.2.0/24 h2-net
sudo podman pod create --name h2-pod --network h2-net --mac-address 08:00:00:00:02:02 --ip 10.0.2.2
sudo podman run --detach --privileged --name h2 --pod h2-pod --cap-add NET_ADMIN $REDIS_IMG $REDIS_ARGS

# Host 3
printf "\n-----Creating host 3-----\n"
sudo podman network create --driver bridge --opt isolate=1 --disable-dns --interface-name h3-br --gateway 10.0.3.30 --route 10.0.1.0/24,10.0.3.30 --subnet 10.0.3.0/24 h3-net
sudo podman pod create --name h3-pod --network h3-net --mac-address 08:00:00:00:03:03 --ip 10.0.3.3
sudo podman run --detach --privileged --name h3 --pod h3-pod --cap-add NET_ADMIN $REDIS_IMG $REDIS_ARGS


# Configure interfaces
printf "\n-----Configuring interfaces-----\n"
interfaces=(h1-br h2-br h3-br)
for iface in "${interfaces[@]}"; do
printf "Interface: %s\n" $iface
# Disable IPv6 on the interfaces, so that the Linux kernel
# will not automatically send IPv6 MDNS, Router Solicitation,
# and Multicast Listener Report packets on the interface,
# which can make P4 program debugging more confusing.
sudo sysctl net.ipv6.conf.$iface.disable_ipv6=1

# Disable tx/rx/sg offloading
sudo ethtool -K $iface tx off
sudo ethtool -K $iface rx off
sudo ethtool -K $iface sg off

# Set the MTU of these interfaces to be larger than default of
# 1500 bytes, so that P4 behavioral-model testing can be done
# on jumbo frames.
sudo ip link set $iface mtu 9500
done

sudo podman kill h3
sudo podman rm -f h3

# Switch
printf "\n-----Creating switch-----\n"
sudo podman run -d \
--name s1 \
--privileged \
--replace \
--network host \
-v ../../examples/switch_container/s1.sh:/s1.sh \
-v ../../load_balancer/build/load_balance.json:/load_balance.json \
--entrypoint /s1.sh \
p4c
17 changes: 17 additions & 0 deletions examples/redis/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
NUM_HOSTS=3
sudo podman kill redis-app
sudo podman rm -f redis-app

for i in $(seq 1 $NUM_HOSTS); do
printf "\n-----Removing host ${i}-----\n"
sudo podman kill h${i}
sudo podman rm -f h${i}
sudo podman pod rm -f h${i}-pod
sudo podman network rm -f h${i}-net
done


printf "\n-----Removing switch-----\n"
sudo podman kill s1
sudo podman rm -f s1
47 changes: 47 additions & 0 deletions examples/redis/cr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash

# Check if exactly two arguments are provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <source_idx> <target_idx>"
exit 1
fi

# Assigning arguments to variables
SOURCE_IDX=$1
TARGET_IDX=$2

CHECKPOINT_DIR=/tmp/checkpoints
CHECKPOINT_PATH=$CHECKPOINT_DIR/checkpoint.tar

SOURCE_HOST=h$SOURCE_IDX
SOURCE_IP=10.0.$SOURCE_IDX.$SOURCE_IDX

TARGET_HOST=h$TARGET_IDX
TARGET_IP=10.0.$TARGET_IDX.$TARGET_IDX
TARGET_MAC=08:00:00:00:0$TARGET_IDX:0$TARGET_IDX

# Creating checkpoint directory
sudo mkdir -p $CHECKPOINT_DIR

# Checkpoint the source container
sudo podman container checkpoint --export $CHECKPOINT_PATH --compress none --keep --tcp-established $SOURCE_HOST
sudo podman rm -f $SOURCE_HOST

# Edit the checkpoint files with new IP
sudo ../../scripts/edit_files_img.py $CHECKPOINT_PATH $SOURCE_IP $TARGET_IP

# Kill and remove the target container
sudo podman container kill ${TARGET_HOST}
sudo podman container rm -f ${TARGET_HOST}

# Restore the container with new settings
sudo podman container restore --import $CHECKPOINT_PATH --keep --tcp-established --ignore-static-ip --ignore-static-mac --pod ${TARGET_HOST}-pod

# Rename the restored container
# --name cannot be used with --tcp-established on restore
sudo podman rename $SOURCE_HOST $TARGET_HOST

# Update the node information
curl -X POST http://127.0.0.1:5000/update_node \
-H "Content-Type: application/json" \
-d "{\"old_ipv4\":\"${SOURCE_IP}\", \"new_ipv4\":\"${TARGET_IP}\", \"dmac\":\"${TARGET_MAC}\", \"eport\":\"${TARGET_IDX}\"}"
13 changes: 13 additions & 0 deletions examples/redis/s1.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
mkdir /pcaps
simple_switch_grpc \
-i 1@h1-br \
-i 2@h2-br \
-i 3@h3-br \
-i 4@h4-br \
--pcap /pcaps \
--device-id 0 \
/load_balance.json \
--log-console \
-- \
--grpc-server-addr 0.0.0.0:50051
Loading

0 comments on commit dd8ef51

Please sign in to comment.