Index: usr.sbin/ctld/ctl.conf.5 =================================================================== --- usr.sbin/ctld/ctl.conf.5 +++ usr.sbin/ctld/ctl.conf.5 @@ -250,6 +250,14 @@ .Sy portal-group is listened by some other host. This host will announce it on discovery stage, but won't listen. +.It Ic dscp Ar value +The DiffServ Codepoint used for sending data. The DSCP can be +set to numeric, or hexadecimal values directly, as well as the +well-defined +.Qq Ar CSx +and +.Qq Ar AFxx +codepoints. .El .Ss target Context .Bl -tag -width indent Index: usr.sbin/ctld/ctld.h =================================================================== --- usr.sbin/ctld/ctld.h +++ usr.sbin/ctld/ctld.h @@ -127,6 +127,7 @@ TAILQ_HEAD(, port) pg_ports; char *pg_offload; char *pg_redirection; + int pg_dscp; uint16_t pg_tag; }; Index: usr.sbin/ctld/ctld.c =================================================================== --- usr.sbin/ctld/ctld.c +++ usr.sbin/ctld/ctld.c @@ -625,6 +625,7 @@ TAILQ_INIT(&pg->pg_ports); pg->pg_conf = conf; pg->pg_tag = 0; /* Assigned later in conf_apply(). */ + pg->pg_dscp = -1; TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next); return (pg); @@ -2181,6 +2182,32 @@ cumulated_error++; continue; } + if (newpg->pg_dscp != -1) { + struct sockaddr sa; + int len = sizeof(sa); + getsockname(newp->p_socket, &sa, &len); + /* + * Only allow the 6-bit DSCP + * field to be modified + */ + int dscp = newpg->pg_dscp >> 2; + if (sa.sa_family == AF_INET) { + if (setsockopt(newp->p_socket, + IPPROTO_IP, IP_TOS, + &dscp, sizeof(dscp)) == -1) + log_warn("setsockopt(IP_TOS) " + "failed for %s", + newp->p_listen); + } else + if (sa.sa_family == AF_INET6) { + if (setsockopt(newp->p_socket, + IPPROTO_IPV6, IPV6_TCLASS, + &dscp, sizeof(dscp)) == -1) + log_warn("setsockopt(IPV6_TCLASS) " + "failed for %s", + newp->p_listen); + } + } error = bind(newp->p_socket, newp->p_ai->ai_addr, newp->p_ai->ai_addrlen); if (error != 0) { Index: usr.sbin/ctld/parse.y =================================================================== --- usr.sbin/ctld/parse.y +++ usr.sbin/ctld/parse.y @@ -41,6 +41,8 @@ #include #include "ctld.h" +#include +#include extern FILE *yyin; extern char *yytext; @@ -60,11 +62,13 @@ %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL %token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE -%token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER FOREIGN +%token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR %token TAG TARGET TIMEOUT +%token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43 +%token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7 %union { @@ -353,6 +357,8 @@ portal_group_redirect | portal_group_tag + | + portal_group_dscp ; portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR @@ -463,6 +469,50 @@ } ; +portal_group_dscp +: DSCP STR + { + uint64_t tmp; + + if (strcmp($2, "0x") == 0) { + tmp = strtol($2 + 2, NULL, 16); + } else if (expand_number($2, &tmp) != 0) { + yyerror("invalid numeric value"); + free($2); + return(1); + } + if (tmp >= 0x40) { + yyerror("invalid dscp value"); + return(1); + } + + portal_group->pg_dscp = tmp; + } +| DSCP BE { portal_group->pg_dscp = IPTOS_DSCP_CS0 ; } +| DSCP EF { portal_group->pg_dscp = IPTOS_DSCP_EF ; } +| DSCP CS0 { portal_group->pg_dscp = IPTOS_DSCP_CS0 ; } +| DSCP CS1 { portal_group->pg_dscp = IPTOS_DSCP_CS1 ; } +| DSCP CS2 { portal_group->pg_dscp = IPTOS_DSCP_CS2 ; } +| DSCP CS3 { portal_group->pg_dscp = IPTOS_DSCP_CS3 ; } +| DSCP CS4 { portal_group->pg_dscp = IPTOS_DSCP_CS4 ; } +| DSCP CS5 { portal_group->pg_dscp = IPTOS_DSCP_CS5 ; } +| DSCP CS6 { portal_group->pg_dscp = IPTOS_DSCP_CS6 ; } +| DSCP CS7 { portal_group->pg_dscp = IPTOS_DSCP_CS7 ; } +| DSCP AF11 { portal_group->pg_dscp = IPTOS_DSCP_AF11 ; } +| DSCP AF12 { portal_group->pg_dscp = IPTOS_DSCP_AF12 ; } +| DSCP AF13 { portal_group->pg_dscp = IPTOS_DSCP_AF13 ; } +| DSCP AF21 { portal_group->pg_dscp = IPTOS_DSCP_AF21 ; } +| DSCP AF22 { portal_group->pg_dscp = IPTOS_DSCP_AF22 ; } +| DSCP AF23 { portal_group->pg_dscp = IPTOS_DSCP_AF23 ; } +| DSCP AF31 { portal_group->pg_dscp = IPTOS_DSCP_AF31 ; } +| DSCP AF32 { portal_group->pg_dscp = IPTOS_DSCP_AF32 ; } +| DSCP AF33 { portal_group->pg_dscp = IPTOS_DSCP_AF33 ; } +| DSCP AF41 { portal_group->pg_dscp = IPTOS_DSCP_AF41 ; } +| DSCP AF42 { portal_group->pg_dscp = IPTOS_DSCP_AF42 ; } +| DSCP AF43 { portal_group->pg_dscp = IPTOS_DSCP_AF43 ; } + ; + + lun: LUN lun_name OPENING_BRACKET lun_entries CLOSING_BRACKET { Index: usr.sbin/ctld/token.l =================================================================== --- usr.sbin/ctld/token.l +++ usr.sbin/ctld/token.l @@ -63,6 +63,7 @@ device-type { return DEVICE_TYPE; } discovery-auth-group { return DISCOVERY_AUTH_GROUP; } discovery-filter { return DISCOVERY_FILTER; } +dscp { return DSCP; } foreign { return FOREIGN; } initiator-name { return INITIATOR_NAME; } initiator-portal { return INITIATOR_PORTAL; } @@ -85,6 +86,28 @@ tag { return TAG; } target { return TARGET; } timeout { return TIMEOUT; } +af11 { return AF11; } +af12 { return AF12; } +af13 { return AF13; } +af21 { return AF21; } +af22 { return AF22; } +af23 { return AF23; } +af31 { return AF31; } +af32 { return AF32; } +af33 { return AF33; } +af41 { return AF41; } +af42 { return AF42; } +af43 { return AF43; } +be { return CS0; } +ef { return EF; } +cs0 { return CS0; } +cs1 { return CS1; } +cs2 { return CS2; } +cs3 { return CS3; } +cs4 { return CS4; } +cs5 { return CS5; } +cs6 { return CS6; } +cs7 { return CS7; } \"[^"]+\" { yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; } [a-zA-Z0-9\.\-@_/\:\[\]]+ { yylval.str = strdup(yytext); return STR; } Index: usr.sbin/ctld/uclparse.c =================================================================== --- usr.sbin/ctld/uclparse.c +++ usr.sbin/ctld/uclparse.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "ctld.h" @@ -607,7 +609,70 @@ ucl_object_tostring_forced(tmp)); } } - } + + if (!strcmp(key, "dscp")) { + if ((obj->type != UCL_STRING) && (obj->type != UCL_INT)) { + log_warnx("\"dscp\" property of portal group " + "\"%s\" is not a string or integer", portal_group->pg_name); + return(1); + } + if (obj->type == UCL_INT) + portal_group->pg_dscp = ucl_object_toint(obj); + else { + key = ucl_object_tostring(obj); + if (strcmp(key, "0x") == 0) + portal_group->pg_dscp = strtol(key + 2, NULL, 16); + else if (strcmp(key, "be") || strcmp(key, "cs0")) + portal_group->pg_dscp = IPTOS_DSCP_CS0; + else if (strcmp(key, "ef")) + portal_group->pg_dscp = IPTOS_DSCP_EF; + else if (strcmp(key, "cs0")) + portal_group->pg_dscp = IPTOS_DSCP_CS0; + else if (strcmp(key, "cs1")) + portal_group->pg_dscp = IPTOS_DSCP_CS1; + else if (strcmp(key, "cs2")) + portal_group->pg_dscp = IPTOS_DSCP_CS2; + else if (strcmp(key, "cs3")) + portal_group->pg_dscp = IPTOS_DSCP_CS3; + else if (strcmp(key, "cs4")) + portal_group->pg_dscp = IPTOS_DSCP_CS4; + else if (strcmp(key, "cs5")) + portal_group->pg_dscp = IPTOS_DSCP_CS5; + else if (strcmp(key, "cs6")) + portal_group->pg_dscp = IPTOS_DSCP_CS6; + else if (strcmp(key, "cs7")) + portal_group->pg_dscp = IPTOS_DSCP_CS7; + else if (strcmp(key, "af11")) + portal_group->pg_dscp = IPTOS_DSCP_AF11; + else if (strcmp(key, "af12")) + portal_group->pg_dscp = IPTOS_DSCP_AF12; + else if (strcmp(key, "af13")) + portal_group->pg_dscp = IPTOS_DSCP_AF13; + else if (strcmp(key, "af21")) + portal_group->pg_dscp = IPTOS_DSCP_AF21; + else if (strcmp(key, "af22")) + portal_group->pg_dscp = IPTOS_DSCP_AF22; + else if (strcmp(key, "af23")) + portal_group->pg_dscp = IPTOS_DSCP_AF23; + else if (strcmp(key, "af31")) + portal_group->pg_dscp = IPTOS_DSCP_AF31; + else if (strcmp(key, "af32")) + portal_group->pg_dscp = IPTOS_DSCP_AF32; + else if (strcmp(key, "af33")) + portal_group->pg_dscp = IPTOS_DSCP_AF33; + else if (strcmp(key, "af41")) + portal_group->pg_dscp = IPTOS_DSCP_AF41; + else if (strcmp(key, "af42")) + portal_group->pg_dscp = IPTOS_DSCP_AF42; + else if (strcmp(key, "af43")) + portal_group->pg_dscp = IPTOS_DSCP_AF43; + else { + log_warnx("\"dscp\" property value is not a supported textual value"); + return (1); + } + } + } + } return (0); }