Hi Andre,

Andre, Pascal wrote:
> Now, would it be possible to declare IPv6 addresses in the same way ?
>  Ex: IPv6addr::3ffe:1111:2222:3333:4444:5556:6666:7777/64/eth0

The /etc/ha.d/resource.d/IPv6addr script is changed and it enabled it to
declare. See attached new patch.
The IPv6addr script splits the argument into pieces that IPv6addr OCF RA
can recognize, and sets it to the following environment variable.
And IPv6addr OCF RA is called.
* OCF_RESKEY_ipv6addr (Ex: 3ffe:1111:2222:3333:4444:5556:6666:7777)
* OCF_RESKEY_cidr_netmask (Ex: 64)
* OCF_RESKEY_nic (Ex: eth0)

And a new parameter cidr_netmask to specify the netmask was added.
Now, a v2 user can specify ipv6addr, cidr_netmask, and nic with instance
parameters.
It has left the method of old specification of the ipv6addr
parameter(<ip>/<prefix-len>).
However, when cidr_netmask is specified, the value of cidr_netmask is used
as prefix-len.
For example:

### example(1) ###
  <primitive id="ip1:1" class="ocf" type="IPv6addr" provider="heartbeat">
    <operations>
      ...snip...
    </operations>
    <instance_attributes id="ip1:1:attr">
      <attributes>
        <nvpair id="ip01" name="ipv6addr" value="2001:db8:90::189"/>
        <nvpair id="ip02" name="cidr_netmask" value="64"/>
        <nvpair id="ip03" name="nic" value="eth0"/>
      </attributes>
    </instance_attributes>
  </primitive>

In this case, netmask (prefix-len) is 64.

### example(2) ###
  <primitive id="ip1:1" class="ocf" type="IPv6addr" provider="heartbeat">
    <operations>
      ...snip...
    </operations>
    <instance_attributes id="ip1:1:attr">
      <attributes>
        <nvpair id="ip01" name="ipv6addr" value="2001:db8:90::189/24"/>
        <nvpair id="ip02" name="cidr_netmask" value="64"/>
        <nvpair id="ip03" name="nic" value="eth0"/>
      </attributes>
    </instance_attributes>
  </primitive>

Also in this case, netmask (prefix-len) is 64.

### example(3) ###
  <primitive id="ip1:1" class="ocf" type="IPv6addr" provider="heartbeat">
    <operations>
      ...snip...
    </operations>
    <instance_attributes id="ip1:1:attr">
      <attributes>
        <nvpair id="ip01" name="ipv6addr" value="2001:db8:90::189/24"/>
        <nvpair id="ip03" name="nic" value="eth0"/>
      </attributes>
    </instance_attributes>
  </primitive>

In this case, netmask (prefix-len) is 24.

We would like to hear any opinion about this.


Best Regards,
Kazunori INOUE


Andre, Pascal wrote:
> Hi Kazunori-san,
> 
> Eventhough I know that backward compatibility with Linux-HA v1 may not be the 
> most important issue, is your modification compatible with v1 ? In other 
> words, how can a v1 user declare the 'nic' to be used for IPv6 addresses ?
> 
> For IPv4, a v1 user had to declare its IP address as follows: 
> <ip>/<prefix-len>/<interface> (ex: 135.9.8.7/24/eth0).
> 
> Now, would it be possible to declare IPv6 addresses in the same way ?
>  Ex: IPv6addr::3ffe:1111:2222:3333:4444:5556:6666:7777/64/eth0
> 
> That's what was done in the patch I proposed a few months ago (the patch you 
> link to in your mail). Unfortunately, it appeared that my patch was too 'v1 
> oriented' ;) and Dejan asked me to add v2 support before re-submitting it. I 
> had a look at what to do for this, without success (I'm quite a newbie about 
> Linux-HA). Without more time to devote on this issue, I put it aside. I'm 
> glad you raised the issue again ;). Now, I would be very thankful if your 
> patch could fix this problem for v1 users too (unless it does it already). 
> Maybe a solution could be to allow both ways to add the 'nic': via the 
> parameter 'nic' or by appending it at the end the IPv6 address string. What 
> do you think ?
> 
> Thanks and regards
> 
> Pascal ANDRE
> 
> 
>> -----Original Message-----
>> From: [email protected]
>> [mailto:[email protected]] On Behalf Of
>> Kazunori INOUE
>> Sent: Tuesday, August 04, 2009 2:54 AM
>> To: [email protected]
>> Cc: [email protected]
>> Subject: [Linux-ha-dev] [PATCH] IPv6addr: Support a parameter
>> to specify interface name
>>
>> Hi lists,
>>
>> I implemented a function to IPv6addr.
>> I'd like to explain the role of attached patch.
>> It's for changeset:cf020d609b57.
>> And it's to add a new parameter "nic" to specify interface.
>> I referred to Dejan's opinion
>> (http://www.gossamer-threads.com/lists/linuxha/dev/55234).
>>
>> I would like to hear your opinions.
>>
>> Best Regards,
>> Kazunori INOUE
>>
> _______________________________________________________
> Linux-HA-Dev: [email protected]
> http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
> Home Page: http://linux-ha.org/
diff -urN linux-ha-dev.org/resources/OCF/IPv6addr.c 
linux-ha-dev.mod/resources/OCF/IPv6addr.c
--- linux-ha-dev.org/resources/OCF/IPv6addr.c   2009-07-30 10:01:41.000000000 
+0900
+++ linux-ha-dev.mod/resources/OCF/IPv6addr.c   2009-08-06 11:06:13.000000000 
+0900
@@ -45,6 +45,8 @@
  *
  * It should be passed by environment variant:
  *     OCF_RESKEY_ipv6addr=3ffe:ffff:0:f101::3
+ *     OCF_RESKEY_cidr_netmask=64
+ *     OCF_RESKEY_nic=eth0
  *
  */
  
@@ -145,11 +147,11 @@
        unsigned int ifr6_ifindex;
 };
 
-static int start_addr6(struct in6_addr* addr6, int prefix_len);
-static int stop_addr6(struct in6_addr* addr6, int prefix_len);
-static int status_addr6(struct in6_addr* addr6, int prefix_len);
+static int start_addr6(struct in6_addr* addr6, int prefix_len, char* 
prov_ifname);
+static int stop_addr6(struct in6_addr* addr6, int prefix_len, char* 
prov_ifname);
+static int status_addr6(struct in6_addr* addr6, int prefix_len, char* 
prov_ifname);
 static int monitor_addr6(struct in6_addr* addr6, int prefix_len);
-static int advt_addr6(struct in6_addr* addr6, int prefix_len);
+static int advt_addr6(struct in6_addr* addr6, int prefix_len, char* 
prov_ifname);
 static int meta_data_addr6(void);
 
 
@@ -159,9 +161,9 @@
 static void byebye(int nsig);
 
 static char* scan_if(struct in6_addr* addr_target, int* plen_target,
-                    int use_mask);
-static char* find_if(struct in6_addr* addr_target, int* plen_target);
-static char* get_if(struct in6_addr* addr_target, int* plen_target);
+                    int use_mask, char* prov_ifname);
+static char* find_if(struct in6_addr* addr_target, int* plen_target, char* 
prov_ifname);
+static char* get_if(struct in6_addr* addr_target, int* plen_target, char* 
prov_ifname);
 static int assign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name);
 static int unassign_addr6(struct in6_addr* addr6, int prefix_len, char* 
if_name);
 int is_addr6_available(struct in6_addr* addr6);
@@ -172,9 +174,11 @@
 {
        char            pid_file[256];
        char*           ipv6addr;
+       char*           cidr_netmask;
        int             ret;
        char*           cp;
-       int             prefix_len;
+       char*           prov_ifname = NULL;
+       int             prefix_len = -1;
        struct in6_addr addr6;
 
        /* Check the count of parameters first */
@@ -204,6 +208,8 @@
                usage(argv[0]);
                return OCF_ERR_ARGS;
        }
+
+       /* legacy option */
        if ((cp = strchr(ipv6addr, '/'))) {
                prefix_len = atol(cp + 1);
                if ((prefix_len < 0) || (prefix_len > 128)) {
@@ -212,10 +218,30 @@
                        return OCF_ERR_ARGS;
                }
                *cp=0;
-       } else {
+       }
+
+       /* get provided netmask (optional) */
+       cidr_netmask = getenv("OCF_RESKEY_cidr_netmask");
+       if (cidr_netmask != NULL) {
+               if ((atol(cidr_netmask) < 0) || (atol(cidr_netmask) > 128)) {
+                       cl_log(LOG_ERR, "Invalid prefix_len [%s], "
+                               "should be an integer in [0, 128]", 
cidr_netmask);
+                       usage(argv[0]);
+                       return OCF_ERR_ARGS;
+               }
+               if (prefix_len != -1 && prefix_len != atol(cidr_netmask)) {
+                       cl_log(LOG_DEBUG, "prefix_len(%d) is overwritted by 
cidr_netmask(%s)",
+                               prefix_len, cidr_netmask);
+               }
+               prefix_len = atol(cidr_netmask);
+
+       } else if (prefix_len == -1) {
                prefix_len = 0;
        }
 
+       /* get provided interface name (optional) */
+       prov_ifname = getenv("OCF_RESKEY_nic");
+
        if (inet_pton(AF_INET6, ipv6addr, &addr6) <= 0) {
                cl_log(LOG_ERR, "Invalid IPv6 address [%s]", ipv6addr);
                usage(argv[0]);
@@ -244,11 +270,11 @@
 
        /* switch the command */
        if (0 == strncmp(START_CMD,argv[1], strlen(START_CMD))) {
-               ret = start_addr6(&addr6, prefix_len);
+               ret = start_addr6(&addr6, prefix_len, prov_ifname);
        }else if (0 == strncmp(STOP_CMD,argv[1], strlen(STOP_CMD))) {
-               ret = stop_addr6(&addr6, prefix_len);
+               ret = stop_addr6(&addr6, prefix_len, prov_ifname);
        }else if (0 == strncmp(STATUS_CMD,argv[1], strlen(STATUS_CMD))) {
-               ret = status_addr6(&addr6, prefix_len);
+               ret = status_addr6(&addr6, prefix_len, prov_ifname);
        }else if (0 ==strncmp(MONITOR_CMD,argv[1], strlen(MONITOR_CMD))) {
                ret = monitor_addr6(&addr6, prefix_len);
        }else if (0 ==strncmp(RELOAD_CMD,argv[1], strlen(RELOAD_CMD))) {
@@ -259,7 +285,7 @@
        /* ipv6addr has been validated by inet_pton, hence a valid IPv6 address 
*/
                ret = OCF_SUCCESS;
        }else if (0 ==strncmp(ADVT_CMD,argv[1], strlen(MONITOR_CMD))) {
-               ret = advt_addr6(&addr6, prefix_len);
+               ret = advt_addr6(&addr6, prefix_len, prov_ifname);
        }else{
                usage(argv[0]);
                ret = OCF_ERR_ARGS;
@@ -271,16 +297,16 @@
        return ret;
 }
 int
-start_addr6(struct in6_addr* addr6, int prefix_len)
+start_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
 {
        int     i;
        char*   if_name;
-       if(OCF_SUCCESS == status_addr6(addr6,prefix_len)) {
+       if(OCF_SUCCESS == status_addr6(addr6,prefix_len,prov_ifname)) {
                return OCF_SUCCESS;
        }
 
        /* we need to find a proper device to assign the address */
-       if_name = find_if(addr6, &prefix_len);
+       if_name = find_if(addr6, &prefix_len, prov_ifname);
        if (NULL == if_name) {
                cl_log(LOG_ERR, "no valid mecahnisms");
                return OCF_ERR_GENERIC;
@@ -313,10 +339,10 @@
 }
 
 int
-advt_addr6(struct in6_addr* addr6, int prefix_len)
+advt_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
 {
        /* First, we need to find a proper device to assign the address */
-       char*   if_name = get_if(addr6, &prefix_len);
+       char*   if_name = get_if(addr6, &prefix_len, prov_ifname);
        int     i;
        if (NULL == if_name) {
                cl_log(LOG_ERR, "no valid mecahnisms");
@@ -331,14 +357,14 @@
 }
 
 int
-stop_addr6(struct in6_addr* addr6, int prefix_len)
+stop_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
 {
        char* if_name;
-       if(OCF_NOT_RUNNING == status_addr6(addr6,prefix_len)) {
+       if(OCF_NOT_RUNNING == status_addr6(addr6,prefix_len,prov_ifname)) {
                return OCF_SUCCESS;
        }
 
-       if_name = get_if(addr6, &prefix_len);
+       if_name = get_if(addr6, &prefix_len, prov_ifname);
 
        if (NULL == if_name) {
                cl_log(LOG_ERR, "no valid mechanisms.");
@@ -356,9 +382,9 @@
 }
 
 int
-status_addr6(struct in6_addr* addr6, int prefix_len)
+status_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
 {
-       char* if_name = get_if(addr6, &prefix_len);
+       char* if_name = get_if(addr6, &prefix_len, prov_ifname);
        if (NULL == if_name) {
                return OCF_NOT_RUNNING;
        }
@@ -441,7 +467,7 @@
 
 /* find the network interface associated with an address */
 char*
-scan_if(struct in6_addr* addr_target, int* plen_target, int use_mask)
+scan_if(struct in6_addr* addr_target, int* plen_target, int use_mask, char* 
prov_ifname)
 {
        FILE *f;
        static char devname[21]="";
@@ -489,6 +515,15 @@
                }
                *plen_target = plen;
 
+               /* If interface name provided, only same devname entry
+                * would be considered
+                */
+               if (prov_ifname!=0 && *prov_ifname!=0)
+               {
+                       if (strcmp(devname, prov_ifname))
+                               continue;
+               }
+
                for (i = 0; i< 4; i++) {
                        addr.s6_addr32[i] = htonl(addr6p[i]);
                }
@@ -527,15 +562,15 @@
 }
 /* find a proper network interface to assign the address */
 char*
-find_if(struct in6_addr* addr_target, int* plen_target)
+find_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname)
 {
-       return scan_if(addr_target, plen_target, 1);
+       return scan_if(addr_target, plen_target, 1, prov_ifname);
 }
 /* get the device name and the plen_target of a special address */
 char*
-get_if(struct in6_addr* addr_target, int* plen_target)
+get_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname)
 {
-       return scan_if(addr_target, plen_target, 0);
+       return scan_if(addr_target, plen_target, 0, prov_ifname);
 }
 int
 assign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name)
@@ -851,6 +886,23 @@
        "      <shortdesc lang=\"en\">IPv6 address</shortdesc>\n"
        "      <content type=\"string\" default=\"\" />\n"
        "    </parameter>\n"
+       "    <parameter name=\"cidr_netmask\" unique=\"0\">\n"
+       "      <longdesc lang=\"en\">\n"
+       "       The netmask for the interface in CIDR format. (ie, 24).\n"
+       "       The value of this parameter overwrites the value of _prefix_\n"
+       "       of ipv6addr parameter.\n"
+       "      </longdesc>\n"
+       "      <shortdesc lang=\"en\">Netmask</shortdesc>\n"
+       "      <content type=\"string\" default=\"\" />\n"
+       "    </parameter>\n"
+       "    <parameter name=\"nic\" unique=\"0\">\n"
+       "      <longdesc lang=\"en\">\n"
+       "       The base network interface on which the IPv6 address will\n"
+       "       be brought online.\n"
+       "      </longdesc>\n"
+       "      <shortdesc lang=\"en\">Network interface</shortdesc>\n"
+       "      <content type=\"string\" default=\"\" />\n"
+       "    </parameter>\n"
        "  </parameters>\n"
        "  <actions>\n"
        "    <action name=\"start\"   timeout=\"15\" />\n"
diff -urN linux-ha-dev.org/resources/heartbeat/IPv6addr.in 
linux-ha-dev.mod/resources/heartbeat/IPv6addr.in
--- linux-ha-dev.org/resources/heartbeat/IPv6addr.in    2008-08-18 
21:32:19.000000000 +0900
+++ linux-ha-dev.mod/resources/heartbeat/IPv6addr.in    2009-08-06 
11:04:48.000000000 +0900
@@ -25,5 +25,24 @@
 OCF_RESOURCE_INSTANCE=${OCF_TYPE}_$1
 export OCF_TYPE OCF_RESOURCE_INSTANCE
 
-OCF_RESKEY_ipv6addr=$1; export OCF_RESKEY_ipv6addr
+# We need to split the argument into pieces that IPv6addr OCF RA can
+# recognize, sed is prefered over Bash specific builtin functions
+# for portability.
+BASEIP=`echo $1 | sed 's%/.*%%'`
+OCF_RESKEY_ipv6addr=$BASEIP; export OCF_RESKEY_ipv6addr
+
+str=`echo $1 | sed 's%^'$BASEIP'*%%'`
+if [ ! -z "$str" ]; then
+    NETMASK=`echo ${str#/} | sed 's%/.*%%'`
+    OCF_RESKEY_cidr_netmask=$NETMASK; export OCF_RESKEY_cidr_netmask
+
+    str=`echo $str | sed 's%^/'$NETMASK'/*%%'`
+    NIC=`echo $str | sed 's%/.*%%'`
+    case $NIC in
+       "")     ;;
+       *)      OCF_RESKEY_nic=$NIC; export OCF_RESKEY_nic
+               ;;
+    esac
+fi
+
 ra_execocf $2
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to