diff --git a/.gitignore b/.gitignore index a451ac6..1a7a50a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ image/bin/list-nodes +image/bin/ipv4 image/opt/cni/bin/* image/build-date !image/opt/cni/bin/node-local diff --git a/build.sh b/build.sh index 784c2d9..72d695b 100755 --- a/build.sh +++ b/build.sh @@ -52,6 +52,7 @@ cmd_image() { go build -ldflags "-extldflags '-static' -X main.version=$__version" \ -o image/bin/list-nodes ./cmd/... strip image/bin/list-nodes + gcc -o image/bin/ipv4 -static ./src/ipv4.c date > image/build-date docker build -t $__image:$__version . } diff --git a/image/bin/xcluster-cni-router.sh b/image/bin/xcluster-cni-router.sh index 77f82cb..4e97f98 100755 --- a/image/bin/xcluster-cni-router.sh +++ b/image/bin/xcluster-cni-router.sh @@ -220,8 +220,13 @@ get_addresses() { fi done - test -n "$a6" && return 0 - test -n "$a4" || return 0 + test -n "$a6" -a -n "$a4" && return 0 + if test -z "$a4"; then + # We have an ipv6 address, but no ipv4. + # We can only handle this case if $IPV6_PREFIX is used. + test -n "$IPV6_PREFIX" && a4=$(ipv4 $a6) + return 0 + fi # We have an ipv4 address, but no ipv6. diff --git a/image/xcluster-cni.sh b/image/xcluster-cni.sh index b361fe1..f956879 100755 --- a/image/xcluster-cni.sh +++ b/image/xcluster-cni.sh @@ -44,11 +44,44 @@ cmd_env() { cmd_pod_cidrs() { cmd_env list-nodes | jq "select(.metadata.name == \"$K8S_NODE\")" > $my_node_info - if test "$(jq .spec.podCIDRs < $my_node_info)" != "null"; then + if test "$(jq .spec.podCIDRs < $my_node_info)" = "null"; then + # Pre v1.16 cluster + if test "$(jq .spec.podCIDR < $my_node_info)" != "null"; then + jq -r '.spec.podCIDR' < $my_node_info + fi + return 0 + fi + + if test "$(jq .spec.podCIDRs[1] < $my_node_info)" = "null"; then + # Single-stack cluster jq -r '.spec.podCIDRs[]' < $my_node_info + return 0 + fi + + # For dual-stack the CNI-plugin must make sure that the first + # address is of the "main" family in the cluster ?!?!?! + if echo "$KUBERNETES_SERVICE_HOST" | grep -q : ; then + # Main family ipv6 + if jq -r '.spec.podCIDRs[0]' < $my_node_info grep -q : ; then + # Ok, correct family + jq -r '.spec.podCIDRs[]' < $my_node_info + else + # Reverse the order + jq -r '.spec.podCIDRs[1]' < $my_node_info + jq -r '.spec.podCIDRs[0]' < $my_node_info + fi else - jq -r '.spec.podCIDR' < $my_node_info + # Main family ipv4 + if jq -r '.spec.podCIDRs[0]' < $my_node_info grep -q : ; then + # Reverse the order + jq -r '.spec.podCIDRs[1]' < $my_node_info + jq -r '.spec.podCIDRs[0]' < $my_node_info + else + # Ok, correct family + jq -r '.spec.podCIDRs[]' < $my_node_info + fi fi + return 0 } # Print the interface that holds the passed address diff --git a/src/ipv4.c b/src/ipv4.c new file mode 100644 index 0000000..fc0695c --- /dev/null +++ b/src/ipv4.c @@ -0,0 +1,24 @@ +#include +#include + + +int +main(int argc, char* argv[]) +{ + if (argc < 2) { + printf("0.0.0.0\n"); + return 0; + } + unsigned char buf[sizeof(struct in6_addr)]; + if (inet_pton(AF_INET6, argv[1], buf) == 1) { + struct in6_addr* ap = (struct in6_addr*)buf; + struct in_addr a4 = {ap->s6_addr32[3]}; + printf("%s\n", inet_ntoa(a4)); + return 0; + } + if (inet_pton(AF_INET, argv[1], buf) == 1) { + printf("%s\n", argv[1]); + return 0; + } + return -1; +}